CSS Variables (Custom Properties): A Practical Guide
What CSS variables are, how they behave, and how to use them for theming and dark mode without a build step.
CSS variables, also called custom properties, are named values you define once in your stylesheet and reuse anywhere. You declare them with a double-dash, like --color-primary: #6C5CE7, and call them with var(--color-primary). Change the value in one place and every rule that references it updates, live in the browser.
How to declare and use them
Most teams define variables on the :root selector so they are available everywhere:
:root {
--color-primary: #6C5CE7;
--space-3: 16px;
--radius: 12px;
}
.button {
background: var(--color-primary);
padding: var(--space-3);
border-radius: var(--radius);
}
You can also supply a fallback for safety: var(--color-primary, #6C5CE7). If the variable is undefined, the browser uses the fallback.
Why they matter
Before custom properties, the only way to share values across a stylesheet was a preprocessor like Sass, which compiles to fixed values at build time. CSS variables are different in one important way: they are live. The browser holds them at runtime, so you can change them with a media query, a class, or JavaScript, and the page responds without recompiling anything.
They cascade and inherit
Custom properties follow the cascade like any other CSS. Define a variable on a parent and its children inherit it. Redefine it on a smaller scope and that scope overrides the value. This is what makes component-level theming clean: set --button-bg on a single card and only that card's buttons change.
Theming and dark mode
This is where variables earn their keep. Define your colors once, then swap them under a media query or a theme class:
:root {
--bg: #ffffff;
--text: #0d0d0d;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0d0d0d;
--text: #ffffff;
}
}
Every element that reads var(--bg) and var(--text) flips automatically. No duplicate stylesheets, no JavaScript required for the basic case.
CSS variables and design tokens
CSS variables are the natural home for design tokens in the browser. Your token pipeline exports a value like color-primary, and it lands in CSS as --color-primary. The naming discipline from a token system, intent over appearance, applies directly here. If tokens are new to you, read Design Tokens Explained, then come back and wire them up as custom properties.
Frequently asked questions
What is the difference between CSS variables and Sass variables?
Sass variables are resolved at build time and become fixed values. CSS variables live in the browser at runtime, so they can change with themes, media queries, or JavaScript after the page has loaded.
Do CSS variables work in all browsers?
Yes. Every current browser supports custom properties. Only very old versions like Internet Explorer 11 lack support, which rarely matters today.
Can I change a CSS variable with JavaScript?
Yes. Use element.style.setProperty('--color-primary', '#00b894') and every rule using that variable updates instantly. This is the basis of runtime theme switchers.
Want a themeable front-end built on solid tokens?
I set up CSS architectures where tokens, variables, and components line up, so theming and dark mode are a config change, not a rewrite. See the work to get a feel for how I build.
See my workRelated posts
View allYears of
Experience
Projects
Finished
Unique
Clients Served
Client
Nationalities
Want to see what I can do?
Reading about it is one thing. Take a look at the products, design systems, and interfaces I've actually shipped, then decide if we're a fit.
View my workLike what you see? You'll find how to reach me on the work page and in the menu.