Component-Level Theming with Scoped CSS Variables
Use scoped CSS custom properties to create per-component theme overrides, enabling localized styling without affecting the global theme.
Detailed Explanation
Scoped CSS Variables for Component Theming
CSS custom properties inherit through the DOM tree, which means you can override variables at any level — not just :root. This enables powerful component-level theming.
Basic Scoping
:root {
--button-bg: #3b82f6;
--button-text: #ffffff;
--button-radius: 0.375rem;
}
.button {
background: var(--button-bg);
color: var(--button-text);
border-radius: var(--button-radius);
}
Local Overrides
<div style="--button-bg: #ef4444; --button-text: #ffffff;">
<button class="button">Danger</button>
</div>
The button inside this wrapper uses red without any additional CSS classes or specificity battles.
Card Variant Pattern
.card {
--card-bg: var(--surface);
--card-border: var(--border);
--card-radius: 0.5rem;
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: var(--card-radius);
}
.card--elevated {
--card-bg: var(--bg);
--card-border: transparent;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
.card--outlined {
--card-bg: transparent;
--card-border: var(--primary);
}
Benefits Over Modifier Classes
Traditional BEM modifiers (.card--blue { background: blue; }) require new CSS rules for each variant. Variable overrides let you create infinite variants through inline styles or parent context, with no additional CSS output.
Combining with Global Tokens
Component tokens should reference semantic tokens, not primitives:
.card {
--card-bg: var(--surface); /* semantic, not --gray-100 */
}
This ensures component variants still respect theme switches.
Use Case
Component library authors and design system engineers who need per-component theming that inherits from the global system while allowing local overrides at any DOM level.