Custom Properties and Theming
Build maintainable design systems using CSS variables, inheritance, fallback values, themes, and dynamic custom-property usage.
CSS Custom Properties
Custom properties are CSS variables whose names begin with --. They participate in the cascade and can be consumed using var().
Unlike preprocessor variables, custom properties exist at runtime and can be changed dynamically, including through JavaScript or different CSS states.
:root {
--space-md: 1rem;
--radius-md: 0.75rem;
--color-primary: #2563eb;
}
.button {
padding: var(--space-md);
border-radius: var(--radius-md);
background: var(--color-primary);
}- Custom properties are runtime CSS values.
- They participate in inheritance and the cascade.
How are CSS custom properties named?
var() Fallbacks
The var() function can provide a fallback value when a custom property is invalid or unavailable in the relevant context. Fallbacks can contain another custom property.
This is particularly useful for component APIs and progressive enhancement.
.button {
color: var(--button-text, white);
background: var(--button-background, #2563eb);
}- Fallbacks make custom-property APIs more resilient.
- Custom properties can reference other custom properties.
What does the second argument of `var(--color, blue)` represent?
Dark Mode and Theme Switching
Themes can be implemented by changing semantic custom properties. The browser's prefers-color-scheme media feature can detect whether the user prefers light or dark appearance.
A robust theme system separates semantic tokens such as --surface and --text from component implementation details.
:root {
--surface: white;
--text: #0f172a;
}
@media (prefers-color-scheme: dark) {
:root {
--surface: #0f172a;
--text: #f8fafc;
}
}
body {
background: var(--surface);
color: var(--text);
}- Separate semantic tokens from component rules.
- Use
prefers-color-schemefor system preference detection.
Which media feature detects a user's preferred color scheme?