Master CSS custom properties (variables) to build maintainable stylesheets, implement dark/light theme switching, and create a design token system.
Background
CSS custom properties are variables native to CSS β no preprocessor needed. They're dynamic (changeable with JavaScript at runtime), inheritable (flow through the DOM), and scope-aware. They're the foundation of modern design systems and theme switching.
π‘ CSS variables syntax: Define with --variable-name: value; inside a selector. Use with var(--variable-name) or var(--variable-name, fallback). :root is the document root β variables defined there are globally accessible. They're case-sensitive (--Color β --color).
πΈ Verified Output:
Step 2: Variable Scope
Write this file:
π‘ Variable scope is DOM-based. A variable defined on .card.danger is only available within .card.danger and its descendants. Children inherit parent variables. This means you can override a single variable at the component level and all nested elements using it update.
πΈ Verified Output:
Step 3: Dark/Light Theme Switching
Write this file:
π‘ Theme switching technique: Define all colors as CSS variables, then redefine the variables under a [data-theme="dark"] attribute selector. Toggle document.documentElement.dataset.theme with JavaScript. The CSS transition creates a smooth animated switch.
πΈ Verified Output:
Step 4: Component Theming
Write this file:
π‘ Component-scoped variables β define the base component using var(--name, default). Override the variables on the variant class (.btn-danger, .alert-warning). The component's CSS never changes β only the variable values change. This is exactly how design systems like MUI and Chakra UI work.
πΈ Verified Output:
Step 5: JavaScript + CSS Variables
Write this file:
π‘ element.style.setProperty('--var', value) updates a CSS variable from JavaScript. The change propagates instantly to every element using that variable β no need to update individual DOM elements. This makes CSS variables the bridge between dynamic JavaScript state and static CSS.
πΈ Verified Output:
Step 6: Design Token System
Write this file:
π‘ Design token hierarchy: Raw primitives (--color-blue-500) β Semantic meaning (--color-primary) β Component use. This separation means rebrand = change primitive, dark mode = change semantic tokens, component = untouched. This is how Figma, Tailwind, and MUI handle theming.
πΈ Verified Output:
Step 7: Responsive Spacing Scale with Variables
Write this file:
π‘ Cascading calc() with variables β define a base unit and derive all other spacing with calc(). At a breakpoint, change only the base and every derived spacing updates. This creates proportionally consistent scaling across screen sizes.
π‘ Capstone recap: This is a complete mini design system β tokens β components β themes. All components use variables exclusively. Dark mode works with a single attribute. Every spacing, color, and radius value has a name and semantic meaning. This is production-grade CSS architecture.