CSS Custom Properties and Theming
40 minWe touched on variables earlier, but their true power shines in **Theming**. Because CSS variables are live and inherit, you can swap entire color palettes by changing a class on the `<body>` or `<html>` tag.
This is how Dark Mode works. You define your colors as variables (e.g., `--bg-color`, `--text-color`). Then, inside a media query `@media (prefers-color-scheme: dark)` or a class `.dark-theme`, you simply update the values of those variables. The entire site updates instantly.
You can also use JavaScript to set variables based on user interaction (like a color picker) or mouse position, enabling dynamic effects that were previously impossible with CSS alone.
Scope is important. You can define variables locally within a component to create isolated themes or 'skins' for specific widgets.
Key Concepts
- Variables enable global theming.
- Dark Mode via `prefers-color-scheme`.
- Class-based theming (e.g., `.dark`).
- JS interaction with `setProperty`.
- Scoped variables for component isolation.
Learning Objectives
Master
- Building a complete Dark Mode system
- Structuring CSS for theming
- Manipulating variables with JavaScript
- Handling system preferences
Develop
- User experience customization
- Scalable design systems
- Accessibility (high contrast modes)
Tips
- Define all theme colors in a separate `:root` block.
- Use HSL colors for easier programmatic manipulation.
- Store the user's theme preference in `localStorage`.
- Use `transition: background-color 0.3s` for smooth theme switching.
Common Pitfalls
- Hardcoding colors instead of using the variables.
- Forgetting to update images or icons for dark mode (they might disappear).
- Flash of unstyled content (FOUC) when loading themes via JS.
- Not checking contrast ratios in both light and dark modes.
Summary
- Theming is easy with CSS variables.
- Dark mode is a standard requirement now.
- Variables bridge the gap between CSS and JS.
- They enable scalable, maintainable design systems.
Exercise
Create a theme system with light and dark mode using CSS variables.
:root {
--bg-color: #ffffff;
--text-color: #333333;
}
[data-theme="dark"] {
--bg-color: #333333;
--text-color: #ffffff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
}
Exercise Tips
- Use prefers-color-scheme media query: @media (prefers-color-scheme: dark) { ... }.
- Toggle theme with JavaScript: document.documentElement.setAttribute('data-theme', 'dark');
- Add transition for smooth theme switching: transition: background-color 0.3s, color 0.3s;
- Create multiple themes: [data-theme='blue'], [data-theme='green'], etc.