This page is part of an ongoing series. We plan to continue the journey outlined here, and will update as we go along
Quartz is, needless to say, pretty awesome. It powers plenty of digital gardens (just like this one!), and it’s made to be extremely customizable- if you know some code, at least. You can add your own plugins that transform pages, you can create custom components to use in your site’s layout, and you can customize your site’s colors to your liking. If you can’t tell, we’ve done all three of these: we made a simple twemoji parsing plugin so we can make all our emojis look nice, we created a custom banner component for our project pages, and we’ve changed up the colors used here pretty heavily, along with some other tweaks to how things work.
However, one thing that we didn’t like about the custom theme options was how they were… honestly kind of boring? Here’s what the default Quartz theme config looks like:
Looking at the configuration docs, these colors are really simple:
docs/configuration.md
theme: configure how the site looks.
cdnCaching: if true (default), use Google CDN to cache the fonts. This will generally be faster. Disable (false) this if you want Quartz to download the fonts to be self-contained.
typography: what fonts to use. Any font available on Google Fonts works here.
[…]
colors: controls the theming of the site.
light: page background
lightgray: borders
gray: graph links, heavier borders
darkgray: body text
dark: header text and icons
secondary: link colour, current graph node
tertiary: hover states and visited graph nodes
highlight: internal link background, highlighted text, highlighted lines of code
textHighlight: markdown highlighted text background
This is pretty barebones, frankly, especially when compared to Obsidian itself: there are no dedicated theme accents or colors here, while Obsidian offers built-in color variables for theming. Other themes make use of their own custom color options using the Style Settings plugin, too, meaning that a lot of users who go out of their way to customize their Obsidian theme would be sorely disappointed with these options. (Btw, if you’re looking for a nice theme, highly recommend AnuPpuccin with the Everforest extended colorscheme. It’s really pretty!)
So, how do we fix this? Easy! We just tear the whole thing apart :3
The Quartz “theme engine”
First things first: if we’re gonna rip up the code, we should probably make sure we know how it works. Luckily, Quartz handles things in a ridiculously easy way when it comes to themes: it takes your config data, and then just slaps it into the stylesheet as a bunch of CSS variables. No, I am not kidding.
Well, that’s simple enough to change, right? After looking at the theme we were currently using in Obsidian (remember AnuPpuccin?) and messing around with it, I ended up with this:
Before you say anything: the Object.keys() here is just pure laziness. I know it isn’t the best. Don’t look at me, okay? )
Alright, great! Now we have some options to choose from for colors, and we’ve handled all the existing ones. We can update our config with these new variables and be on our way.
Next step: just find and replace all the old variables with the new ones. That seems pretty easy!
Obligatory “it was not that easy” moment
Just kidding, yes it is :3c with some caveats, though.
Find and replace
If you want to do this yourself, make sure that you find and replace all the variable names in these folders:
quartz/styles
quartz/components
I also want to note that you may need to be careful what order you replace them in so that you don’t end up having to search for --basegray when you replace --light with --base. Don’t ask how I know.
Highlight styles
This gets into something that I’m going to talk about next, but you may want to double check that your highlight and accent colors have enough contrast to be visible on each other. If that’s not the case for you- let’s say, because you made them the same color for ease- then you may want to open your quartz/styles/base.scss and do some replacing:
&.internal { text-decoration: none; - background-color: var(--highlight); + background-color: rgb(from var(--highlight) r g b / 10%); padding: 0 0.1rem; border-radius: 5px; line-height: 1.4rem; }
Caveats on compatibility
The from [...] syntax used here is called relative color syntax, and it’s a pretty new feature. It should be supported in the current version of all major browsers, but older browsers and some specialty browsers may not support it.
If you’re worried about this, then there are some steps you can take:
Change your theme to use destructured RGB values instead of hex codes, like this: base: "44, 49, 65"
Replace the instances of var(--[key]) in your stylesheets with rgb(var(--[key]))
For places that need transparency, use this instead: rgba(var(--[key]), [alpha])
That should give you better compatibility with other browsers. It’s also a lot easier to use, honestly, but the extra work of setting everything to use the RGB values was more than I wanted to do at the moment
Fixing opengraph image generation
Turns out, making changes to the theme like this also breaks the CustomOgImage plugin due to it relying on your config’s theme colors. This is another easy fix: just open up quartz/util/og.tsx, replace all the old variable/property names (like darkgray) with the new ones, and you should be good to go.
Using the new theme colors
So, now we have some new themes with new built-in color variables to use. Where do we use them, though? Callouts.
If you haven’t realized it by now, callouts are one of our favorite features to use. This page being full of them should probably have hinted at that, eheh.
With a fresh install of Quartz, you’ve got a handful of callouts to start with. The problem here, though, is that all of the coloring for them is hard-coded to some random hex codes:
This is fine for the base themes, and probably fine for most people really. But if you’re going to customize your theme, it’s probably a good idea to make sure that colorful things like this synergize well with the text and background, and that’s where our extra colors come in.
Time for more copy-paste-editing!
/* [...] */&[data-callout] { --color: var(--blue); --border: rgb(from var(--blue) r g b / 25%); --bg: rgb(from var(--blue) r g b / 10%); --callout-icon: var(--callout-icon-note); } &[data-callout="abstract"] { --color: var(--blue); --border: rgb(from var(--blue) r g b / 25%); --bg: rgb(from var(--blue) r g b / 10%); --callout-icon: var(--callout-icon-abstract); } &[data-callout="info"], &[data-callout="todo"] { --color: var(--cyan); --border: rgb(from var(--cyan) r g b / 25%); --bg: rgb(from var(--cyan) r g b / 10%); --callout-icon: var(--callout-icon-info); }/* [...] */
Since all of the colors we added are under handy variables, we can just replace all the ugly hex codes with those. The results are pretty nice, too:
Green means go
…
Red means oh no
…
Purple means... you know
…
Orange is just for show
…
Yellow goes with the flow
…
Blue is so-so
…
Cyan is best though
…
(For now this is a just a good example of using the colors, but in the future this will be a useful demo for multi-themes )
Addendum: Header and Decoration Colors [10.21.2025]
Coming back to this, we also went ahead and made it possible to color the headers and decorations (ie. italic and bold text) on the site, just for funsies! This one was also pretty easy to do thankfully. We added boolean properties called coloredHeaders and coloredDecoration to the theme config, implemented them so that having them set to true would set up color variables for each part, then edited the base.scss file to apply those colors. The result?
It’s kinda pretty methinks :3c
And just neat in general
Look at all the colors!
Isn’t this so nice
I don’t have any jokes for this part, sorry
Aaaand here’s the last one
Cool, huh?
In lieu of posting the actual code, I’m leaving that part as a challenge to anyone who wants to do it themselves. Can’t be too hard, right? uwu
Even further beyond
Going back to the idea of multi-themes, the next thing we plan to do is set up options to allow multiple palettes and themes to choose from. Admittedly, this is for selfish reasons: we like to change our themes from time to time when things feel same-y, hah. However, it also benefits anyone visiting the site that may have certain preferred colors, or anyone that needs a palette with higher/lower contrast or saturation.
Once we get around to that, we’ll be sure to either write a new post or update this page!
That’s all for now! If you liked reading this and are curious about other stuff we’ve done, consider checking out our projects or our other writing!