I switched from Sass variables to CSS custom properties about three years ago and haven't looked back. The runtime behaviour is the feature — you can't do dark mode, theme switching, or component-level overrides cleanly with Sass variables alone.
The Key Difference From Sass Variables
Sass variables are a preprocessor feature. They get compiled to static values before the browser ever sees them. $brand-blue becomes #3B82F6 in the output CSS. You can't change a Sass variable at runtime, in a media query, or per component.
CSS custom properties cascade and inherit like any other property. Define them on :root and they're available everywhere. Override them on a specific selector and everything inside that element gets the override.
Setting Up a Token System
Put all your design tokens on :root:
:root {
--bg-base: #0F172A;
--clr-primary: #3B82F6;
--text-body: #E2E8F0;
}To retheme the entire site, change the values in :root only.
Dark Mode Without a Class Toggle
With CSS custom properties, dark mode requires almost no JavaScript:
:root { --bg: #ffffff; --text: #111827; }
@media (prefers-color-scheme: dark) {
:root { --bg: #0F172A; --text: #E2E8F0; }
}Every element that uses var(--bg) automatically switches. No JavaScript class toggling required.
Component-Level Overrides
The cascade makes per-component theming clean. A card component might define its own surface colour, overriding the global token only within its scope.