A few weeks ago, I added an option to toggle between dark and light themes to this blog. After exploring some options, I decide to store the color tokens with Sass and assign them to CSS variables.

Setting Up Design Tokens

Design tokens are values you use for your design system. It serves as a guideline to keep your brand overall feel consistent.

If you’ve been hardcoding the color values in the CSS, you want to set those colors with CSS variables so you can reuse them in your CSS file.

For a personal project where you’re the sole author, the design token name formats are flexible as long they make sense to you. I usually choose a few base colors and play around with the opacity value.

Color Picking Tips — You can adjust the lightness in the LCH value if you want something lighter or darker. You can use a tool like LCH Colour picker to adjust the LCH values.

I store those design tokens as the Sass variables so they’re not exposed in the stylesheet.

// Dark Colors
$color-orange-400: hsl(27, 100%, 79%);
$color-orange-400-10: hsla(27, 100%, 79%, .1);
$color-orange-400-50: hsla(27, 100%, 79%, .5);
$color-charcoal-400: hsl(0, 0%, 2%);
$color-charcoal-400-10: hsla(0, 0%, 2%, .1);
$color-charcoal-300: hsl(0, 0%, 11%);
$color-green-400: hsl(105, 100%, 75%);
$color-green-400-10: hsla(109, 100%, 77%, .1);
$color-dirtwhite-400: hsl(60, 36%, 96%);
$color-dirtwhite-400-30: hsla(60, 36%, 96%, .3);

// Light Colors
$color-linen-400: hsl(30, 58%, 93%);
$color-linen-500: hsl(33, 45%, 87%);
$color-linen-500-10: hsla(33, 45%, 87%, .1);
$color-oil-400: hsl(32, 29%, 10%);
$color-oil-400-30: hsla(32, 29%, 10%, .3);
$color-darkpurple-400: hsl(266, 45%, 59%);
$color-darkpurple-400-10: hsla(266, 45%, 59%, .1);
$color-darkpurple-400-50: hsla(266, 45%, 59%, .5);
$color-rose-400: hsl(353, 54%, 55%);
$color-rose-400-10: hsla(353, 54%, 55%, .1);

Set Default Theme

With color variables ready, you can set the default theme color in :root by assigning them to your design tokens as CSS variables. You can have fewer or more variables depending on how you style your site. The idea is to start with some simple tokens like background, accent, and text color. I used to have a dark theme as the default, but I decided to set the light theme as the default.

You can’t assign Sass variable directly to CSS variable. You have to interpolate the variable with #{} to make it work with CSS built-in variables.

:root {
	--theme-color-background-400: #{$color-linen-400};
	--theme-color-background-500: #{$color-linen-500};
	--theme-color-background-500-10: #{$color-linen-500-10};
	--theme-color-accent-400: #{$color-darkpurple-400};
	--theme-color-accent-400-10: #{$color-darkpurple-400-10};
	--theme-color-accent-400-50: #{$color-darkpurple-400-50};
	--theme-color-foreground-400: #{$color-rose-400};
	--theme-color-foreground-400-10: #{$color-rose-400-10};
	--theme-color-text: #{$color-oil-400};
	--theme-color-shadow: #{$color-oil-400-30};

You’re going to replace the colors in your CSS files with those variables. If you’ve been passing the Sass color values directly, you want to take advantage of CSS variables. Instead of writing color: $theme-color-text, you can write it like this:

body {
	color: var(--theme-color-text);

Adding Dark Theme Support

It’s straightforward to add dark theme support. I’m borrowing this technique Ethan Marcotte’s recent update.

We want to assign a different color to the design tokens by using @media query to check the user device preferences. We’re will apply the dark color values when the :root or html document doesn’t have data-site-theme as the attribute.1

@media (prefers-color-scheme: dark) {
	:root:not([data-site-theme]) {
		--theme-color-background-400: #{$color-charcoal-400};
		--theme-color-background-500: #{$color-charcoal-300};
		--theme-color-background-500-10: #{$color-charcoal-400-10};
		--theme-color-accent-400: #{$color-orange-400};
		--theme-color-accent-400-10: #{$color-orange-400-10};
		--theme-color-accent-400-50: #{$color-orange-400-50};
		--theme-color-foreground-400: #{$color-green-400};
		--theme-color-foreground-400-10: #{$color-green-400-10};
		--theme-color-text: #{$color-dirtwhite-400};
		--theme-color-shadow: #{$color-dirtwhite-400-30};

You can check if your site theme is working by emulating the dark theme with Chrome Dev Tools by pressing Command-Shift-P and search for “emulate dark” for the command to emulate dark theme.

It’s not enough to automatically support dark theme. The next thing you want to do is to allow readers to choose the theme they want to keep when they visit your site. I will cover this topic in a separate post.

  1. The custom data-site-theme attribute will be useful when we want to build a feature to allow users to select a specific theme.