How to create light and dark color modes with CSS

Last week, we looked at how to create accessible and semantic color palettes as part of my deep dive into how I’m building Kelp, my UI library for people who love HTML.
Today, I wanted to show you how I’m implementing light and dark modes. Let’s dig in!
Base Colors For this article, we’ll look at one of our semantic colors: –color-primary-*.
All of the others work the same way, and focusing on just one will make this easier to explain and understand.


This content originally appeared on Go Make Things and was authored by Go Make Things

Last week, we looked at how to create accessible and semantic color palettes as part of my deep dive into how I’m building Kelp, my UI library for people who love HTML.

Today, I wanted to show you how I’m implementing light and dark modes. Let’s dig in!

Base Colors

For this article, we’ll look at one of our semantic colors: --color-primary-*.

All of the others work the same way, and focusing on just one will make this easier to explain and understand.

Our color palette currently includes the following CSS variables defined on the :root element.

:where(:root) {

	--color-primary-fill-muted: var(--color-blue-95);
	--color-primary-fill-accent: var(--color-blue-90);
	--color-primary-fill-vivid: var(--color-blue-50);
	--color-primary-border-muted: var(--color-blue-90);
	--color-primary-border-accent: var(--color-blue-80);
	--color-primary-border-vivid: var(--color-blue-60);
	--color-primary-on-muted: var(--color-blue-30);
	--color-primary-on-accent: var(--color-blue-20);
	--color-primary-on-vivid: white;
	--color-primary-outline: var(--color-blue-50);

}

These are the default “light theme” styles.

Activating dark mode

To enable dark mode, we’ll use a .kelp-theme-dark class.

I originally planned to use a data attribute—[data-kelp-theme="dark"]—but because of CSS specificity and how the cascade is ordered, some light theme variables were sticking around even when dark mode was enabled.

In the same cascade layer as where the default colors are defined, I add the .kelp-theme-dark class and reassign any applicable variables to new color values.

:where(:root) {
	/* default colors */
}

.kelp-theme-dark {
	--color-primary-fill-muted: var(--color-blue-20);
	--color-primary-fill-accent: var(--color-blue-30);
	--color-primary-border-muted: var(--color-blue-30);
	--color-primary-border-accent: var(--color-blue-40);
	--color-primary-on-muted: var(--color-blue-95);
	--color-primary-on-accent: var(--color-blue-95);
	--color-primary-outline: var(--color-blue-70);
}

From testing, I found that the *-vivid colors looked great in light and dark mode, so I don’t change those.

I repeat this pattern with all of my semantic colors. I change some other colors, too.

For example, there are variables for body, text, and link colors. They all get updated in dark mode.

:where(:root) {
	--color-background: white;
	--color-text-normal: var(--color-gray-10);
	--color-text-link: var(--color-blue-50);
	--color-text-link-hover: var(--color-blue-40);
}

.kelp-theme-dark {
	--color-background: var(--color-gray-10);
	--color-text-normal: white;
	--color-text-link: var(--color-blue-70);
	--color-text-link-hover: var(--color-blue-80);
}

Light Mode Override

One other thing I wanted was the ability to activate the dark mode theme on a page, but override it to light mode in select elements or areas on the page.

Where I define my default light mode styles on the :root element, I also define them on the .kelp-theme-light class.

:where(:root),
.kelp-theme-light {

}

This means you can do stuff like this…

<body class="kelp-theme-dark">
	<h1>Hello world!</h1>
	<p>This section is in dark mode.</p>
	<button>Say Hi</button>

	<div class="kelp-theme-light">
		And everything in here is styled in light mode.
	</div>
</body>

Switching Color Modes

In the past, I’ve used CSS and the prefers-color-scheme: dark media query to automatically toggle between light and dark mode.

@media (prefers-color-scheme: dark) {
	/* Dark mode CSS variables */
}

That totally works, but some folks implementing Kelp may want to enable only light mode or only dark mode.

And some may want to include a toggle so that users can choose between light mode, dark mode, or whatever their OS settings currently are.

So, I decided to write a little JavaScript snippet that automatically detects the user’s system preferences and sets the correct class on the html element. It also automatically updates the class if the user changes their OS settings.

/**
 * Automatically toggle dark mode based on users prefers-color-scheme OS setting
 */
(() => {

	const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
	document.documentElement.classList.toggle('kelp-theme-dark', prefersDarkMode.matches);

	prefersDarkMode.addEventListener('change', (event) => {
		document.documentElement.classList.toggle('kelp-theme-dark', event.matches);
	});

})();

One of the features I’ll be adding to Kelp is a light/dark mode toggle for people who want to control it manually instead (which would replace this snippet).

Dig into Kelp

Kelp officially launched over the weekend!

The source code is fully available and unminified, and the docs are rapidly getting built out. Over the next few weeks, I’ll be releasing various Web Components to add more interactivity to the library, and tools to make customizing it even easier.

If you have any questions, feature requests, or other comments, reach out and let me know!

Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.


This content originally appeared on Go Make Things and was authored by Go Make Things


Print Share Comment Cite Upload Translate Updates
APA

Go Make Things | Sciencx (2025-06-23T14:30:00+00:00) How to create light and dark color modes with CSS. Retrieved from https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/

MLA
" » How to create light and dark color modes with CSS." Go Make Things | Sciencx - Monday June 23, 2025, https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/
HARVARD
Go Make Things | Sciencx Monday June 23, 2025 » How to create light and dark color modes with CSS., viewed ,<https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/>
VANCOUVER
Go Make Things | Sciencx - » How to create light and dark color modes with CSS. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/
CHICAGO
" » How to create light and dark color modes with CSS." Go Make Things | Sciencx - Accessed . https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/
IEEE
" » How to create light and dark color modes with CSS." Go Make Things | Sciencx [Online]. Available: https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/. [Accessed: ]
rf:citation
» How to create light and dark color modes with CSS | Go Make Things | Sciencx | https://www.scien.cx/2025/06/23/how-to-create-light-and-dark-color-modes-with-css/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.