Over a year ago, I wrote about updating this blog’s theme and Hugo back-end, embarrassingly vowing that it “will rise again.” Then the poor thing just lay there.1 In the end, my excitement to use the new thing was swept away by a vortex of responsibilities and by the introduction of some other new thing2 that made the now-old new thing feel obsolete. Now that I’m in spring break, I’ve had a chance to update it all again so that I might actually do the thing. Before getting too far, though, I wanted to share some CSS tweaks that might be helpful for anyone else who uses Quarto.
1 Bringing balance to the force
Quarto has a built-in method for allowing users to choose between two themes, which it calls “light” and “dark.” These names suggest more than they should, since each theme could be anything, and the toggle switch is unlabeled.
CSS also has a built-in method for allowing users to choose between two themes. Because it depends upon the settings from a user’s device, CSS is more accurate in calling these options “light” and “dark.”
Unfortunately, these interfaces don’t speak to each other without some tweaking, so I added a switch into the .scss files for each of the themes Quarto lets me set. To do so, I first had to set both the “light” and “dark” theme to the same built-in theme, Litera. But I also added custom .scss files for these themes, which would make the web page style appear differently depending on the toggle at the top. Here’s the relevant section in the “_quarto.yml” file:
format:
html:
theme:
light: [litera, styles.scss]
dark: [litera, styles-alt.scss]
Next, I added CSS media queries into the .scss files. For “styles.scss,” any dark-mode changes should go between the curly braces after the prefers-color-scheme: dark
media query:
@media (prefers-color-scheme: dark) {
...
}
It’s counterintuitive, but the same dark mode style definitions live under prefers-color-scheme: light
in the “styles-alt.scss” file:
@media (prefers-color-scheme: light) {
...
}
I had to do some other tweaking to get things working correctly,3 but these got me 80% of the way. Now, my website effectively offers four themes, with the default theme always respecting a user’s dark-mode preferences and the alternative theme always showing the opposite.
2 Going negative with style
White figures look out of place on a dark-mode background, but CSS has some tricks to help them fit in. The primary trick is to set an image style definition using filter: invert(1)
. This filter turns all whites to black, and all blacks to white. But while my light-mode background is white, my dark-mode background is bluish purple, making all the black images look out of place. To correct for this aggressive negativity, other color filters came in handy, as suggested by an answer on Stack Overflow, ultimately landing somewhere nice: filter: sepia(50%) hue-rotate(30deg) saturate(500%) invert(0.9);
.
That solves one problem but introduces others. For starters, I might sometimes describe a figure in the text of a post, referring to a color that is absent in the dark-mode figure. So I added definitions for the :hover
pseudo-class to undo the color filtering when a user hovers over an image. Additionally, I might occasionally want to show a photo that isn’t a representational figure, and they would look bad with these color filters. So I defined specific circumstances when filtering should be skipped and specified them with selectors:
.figure p img, div.cell-output-display p img, p.card-img-top img {
filter: sepia(50%) hue-rotate(30deg) saturate(500%) invert(0.9);
}
img.noinvert, img.photo, .menu ul li.left a img, img[src$=".jpg"], img[src*="-noinvert"], .figure p img:hover, div.cell-output-display p img:hover, p.card-img-top img[src$=".jpg"], p.card-img-top img[src*="-noinvert"] {
filter: sepia(0%) hue-rotate(0deg) saturate(100%) invert(0) !important;
}
These options make it possible to avoid color modification for certain images by serving them as “.jpg” files, by adding “-noinvert” into the file names, or by giving them a “noinvert” style class in HTML or Markdown:
3 Cleaning up the crumbs
Lastly, I wanted the navigation bar to include links to other parts of my site, so I added a Quarto-native menu in the nav bar:
website:
navbar:
left:
- text: "/ blog"
menu:
- text: "/ blog"
href: "/"
- text: " / about"
href: "https://jmclawson.net/about.php"
...etc...
But I wanted these to be simple, so more CSS tweaks let me overlap the repeated “/ blog” menu title and menu option:
@media (min-width: 992px) {
.navbar-expand-lg .navbar-nav .dropdown-menu {
top: -0.1em;
font-size: .9625rem;
}
}
@media (max-width: 991.98px) {
.navbar ul.dropdown-menu.show {
margin-top: -2.45em;
margin-left: 0.064em;
}
}
4 Now to do the thing
More styling tweaks will certainly distract me,4 but I want now to work on writing up some projects and moving forward with others. This time, I know better than to promise necromancy.
Footnotes
Since publishing this post, I’ve made bigger changes to the website, as of August 2023, elevating the “blog” subsection and replacing some stale PHP breadcrumbs with Quarto underpinnings.↩︎
See Quarto, especially the part about creating a blog.↩︎
Big things included setting actual light mode options for code and other elements in “styles-alt.scss” by setting options under
prefers-color-scheme: dark
. It’s a weird double negative, but necessary.↩︎Especially once Quarto 1.3 is out, adding some features and fixing this annoying bug.↩︎
Citation
@misc{clawson2023,
author = {Clawson, James},
title = {CSS {Tweaks} for {Quarto}},
date = {2023-04-03},
url = {https://jmclawson.net/posts/quarto-css},
langid = {en}
}