Implementing Dark Mode in React Applications
Learn how to build a dark mode toggle that persists user preferences and handles system-level settings seamlessly.
Discover how CSS custom properties make managing multiple themes simple and maintainable across your entire design system.
Building a theme system without CSS variables is like managing a spreadsheet with hardcoded values everywhere. You're stuck. One color change ripples through your entire codebase, and you'll spend hours finding every instance.
CSS custom properties—what we call CSS variables—solve this elegantly. They're not just a convenience. They're the foundation of any professional design system. We're going to show you exactly how they work and why you'll wonder how you ever built themes without them.
CSS variables are declared using double hyphens:
--color-primary
. You define them in a scope—usually
:root
for global use—and reference them with
var(--color-primary)
wherever you need them.
Here's the real magic: they're inherited. A variable set on the root cascades down to every element. Want to change your primary color? Update it once in
:root
, and it updates everywhere instantly. No compilation step. No build process. Just CSS doing what it does best.
Unlike SASS variables or Less variables, CSS variables work at runtime. That means you can change them with JavaScript, apply them conditionally, and even animate them. They're dynamic in ways preprocessor variables simply can't match.
A solid variable system needs structure. You'll want semantic naming: instead of
--color-blue-300
, use
--color-primary
. Instead of
--size-16px
, use
--spacing-md
.
This approach means your HTML doesn't care what the actual color is. A button styled with
background: var(--color-primary)
works perfectly in light or dark mode. You just change the variable value. No class changes. No element modifications.
We recommend organizing variables into groups: colors, spacing, typography, shadows, transitions. About 30-40 variables covers most projects. More than that and you're probably overcomplicating things.
This is where CSS variables shine compared to every other approach. To switch themes, you just redefine your variables. That's it.
Add a
data-theme="dark"
attribute to your HTML element, then override your variables in a media query or class. Your entire design flips instantly. Colors, spacing, shadows—everything follows the variable definitions.
Detect preference:
Use
prefers-color-scheme
media query to detect system settings
Set data attribute: Apply a theme attribute to the root element based on user choice
Override variables: Use CSS selectors to redefine variables for each theme
Persist preference: Save the choice to localStorage so it persists across sessions
Themes work purely through CSS. JavaScript adds the toggle and persistence, but the visual switching happens instantly in the browser's rendering engine.
No style recalculation across hundreds of rules. You're just updating variable values. The browser knows exactly what changed and re-renders efficiently.
Change themes based on time of day, user preference, or even A/B testing. You're not locked into build-time decisions.
Adding a third theme? Just add another variable set. Your HTML and components don't change. Your design system grows without complexity.
You don't need to rebuild your entire site to use CSS variables. Start with your most commonly changed properties—colors, typically. Define them in
:root
, update your selectors to use
var()
instead of hardcoded values, and add a theme toggle. You'll be surprised how quickly this becomes your new default.
The beauty of CSS variables is that they're simple. They don't require a build step, a library, or a framework. They're just CSS doing what it's supposed to do—cascade, inherit, and adapt. Once you've built a theme system with variables, you'll wonder why anyone still uses hardcoded colors.
CSS custom properties are supported in all modern browsers. If you need to support Internet Explorer 11, you'll need a fallback strategy using CSS-in-JS or a preprocessor. For projects targeting modern browsers (2020+), CSS variables work reliably across Chrome, Firefox, Safari, and Edge.
Editorial Team
Written by the Chromatic Studios Editorial Team, focused on practical, tested guidance for theme switching and dark mode implementation.
Learn how to build a dark mode toggle that persists user preferences and handles system-level settings seamlessly.
Ensure your theme switcher meets accessibility standards while providing excellent user experience across all themes.
Master the fundamentals of design tokens to create scalable, consistent, and flexible theme systems.