Dark theme with Stitches

Integrate dark theme support with Stitches on Gatsby.

After tinkering a bit with Stitches, I am very excited to see the improvements in DX, variant-first support, and performance being made in the CSS-in-JS space! Definitely give their documentation a peruse to see all the brilliance being done.

While exploring this library, I found a small theming gotcha when integrating it with my Gatsby site. If you are curious about using Stitches with Gatsby supporting a dark theme, read on to see my current solution.

Switching to Stitches

Just as an experiment to test out Stitches, I decided to swap out styled-component with @stitches/react. I wanted to explore how easy the migration would be and what was required to support my site's dark theme.

Swapping components was very straightforward, especially with the help of the CSS-in-JS VS Code plugin. My initial reason for authoring my components using the tagged template literal method was to maintain closer compatibility with CSS. However, object styles are here to stay and are a safe and more versatile structure for storing styles.

A small plus, object styles are also a tad faster than runtime-parsed template strings. They also work better with libraries that support a typed interface (ex: vanilla-extract, Stitches).

Theming with Stitches in Gatsby

Back to the theming problem! The only other migration step was to update the theming layer. I followed the dark theme pattern well explained and shared from Josh Comaeu – thanks Josh! Using the Stitches getCssString helper, I was able to simplify my code a good bit. Stitches handles the addition of CSS custom properties based on your theme configuration, allowing me to remove the chunk of code that was manually handling this step.

Here is the final required code used in the site's SRR step:

This is a slight variation of Josh's strategy and solution outlined in the Stitches tutorial. For some extra reading, I encourage checking out Josh's full dark theme solution or digging into the source code example!

Final adjustments

The only other modification is to update the ThemeContext to toggle the appropriate className on the root document element:

When running in development, the site may initially load in the default light mode. The dark theme CSS custom properties are added to the page when darkTheme.className is used in ThemeContext.tsx. I'm not a Stitches pro, but looking at the current source, it appears this occurs in the className getter function which triggers a stylesheet update. Note that this may change in the future, as Stitches is in beta.

When built for production, however, the pages are statically generated. The Theme Context should be run and rendered which will add the dark theme variables to the static version of the site, avoiding the flash of the light theme on the initial page load.


This was a pretty niche problem, but I thought I'd share my current solution as I hadn't discovered one myself in the docs or example repos. Happy styling with Stitches, and big thanks to the team's awesome work. Looking forward to seeing Stitches evolve even more. 🧶🪡

Subscribe to the newsletter

Be the first to know when I post something new! Thoughts about code, design, startups and other interesting things.