Imagine your brand colour appears in 40 places in your CSS, and you're asked to make it slightly greener. With CSS variables, officially called custom properties, you change the value in one place and the whole site updates.
Variables also make CSS easier to read. var(--color-danger) tells you what a colour is for, while #d33f49 doesn't. And because variables can change depending on where they're used, they're the technique behind dark mode and colour themes on most modern websites, including this one.
How to define and use a CSS variable
:root {
--brand: #17a865;
--radius: 12px;
}
.button {
background: var(--brand);
border-radius: var(--radius);
}- Variable names start with two hyphens, as in
--brand. :rootrefers to the<html>element, so variables defined there are available everywhere on the page.- Read a variable's value with
var(--name).
Variable names are case-sensitive: --Brand and --brand are two different variables.
Fallback values
var(--accent, orange) uses orange if --accent hasn't been defined. Fallbacks are useful in reusable components, where you can't be sure the page using them has set every variable.
How variables cascade and inherit
Variables follow the normal CSS rules. You can redefine a variable on any element, and its children see the new value. That makes themes and component variations straightforward:
.card { --bg: white; background: var(--bg); }
.card.dark { --bg: #15161b; }The same idea powers dark mode: define light colours on :root, then redefine the same variables inside a prefers-color-scheme: dark media query. Every rule that uses the variables switches automatically.
Changing variables with JavaScript
document.documentElement.style.setProperty('--brand', 'hotpink');One line of JavaScript restyles everything that uses --brand. This is how colour pickers, theme switchers and "large text" buttons are often built.
Variables in calculations
Variables work inside other functions, which makes them even more powerful. You can store a base unit and multiply it, or store numbers and add units later:
:root { --space: 8px; --cols: 3; }
.card { padding: calc(var(--space) * 2); }
.grid { grid-template-columns: repeat(var(--cols), 1fr); }This is how spacing scales and grids in design systems are built: change --space once and every gap, margin and padding that uses it changes in proportion. You can also combine variables with clamp() and color-mix() to build fluid sizes and colour tints from a few base values.
CSS Variables Syntax
Custom properties
:root { --main-color: #4467ff; }
.title { color: var(--main-color); }
.title { color: var(--accent, tomato); } /* with fallback */CSS Variables Summary
- CSS variables store a value once so you can reuse it everywhere.
- Define them with
--name: valueand read them withvar(--name). - Variables on
:rootare available on the whole page. - Redefining a variable on an element changes it for that element's children, which makes themes easy.
- JavaScript can update a variable and restyle the page instantly.
CSS Variables Examples
Each example runs in the page. Edit the code and press Run to see what changes.
A themed button set
Change --brand on line 2 and run. Every button updates.
<button class="btn">Save</button>
<button class="btn outline">Cancel</button>
<button class="btn big">Get started</button>:root {
--brand: #17a865;
--ink: #15161b;
--radius: 12px;
--pad: 10px 18px;
}
.btn {
padding: var(--pad);
border: 2px solid var(--ink);
border-radius: var(--radius);
background: var(--brand);
color: white;
font: 700 15px sans-serif;
}
.btn.outline { background: transparent; color: var(--ink); }
.btn.big { --pad: 16px 28px; --radius: 999px; }Line-by-line explanation
- Lines 1 to 6Define the design decisions once, on
:root. - Lines 9 to 12Use them with
var(). - Line 18Override variables just for large buttons. Padding and radius change, and nothing else needs rewriting.
Light and dark themes
Press the button. JavaScript only switches a class; the variables do the rest.
<div class="app" id="app">
<h3>Settings</h3>
<p>Theme switching with CSS variables.</p>
<button onclick="document.getElementById('app').classList.toggle('dark')">Toggle theme</button>
</div>.app {
--bg: #fbf7f0;
--text: #15161b;
--card: white;
background: var(--bg);
color: var(--text);
padding: 20px;
border-radius: 16px;
font-family: sans-serif;
transition: background 0.3s, color 0.3s;
}
.app.dark {
--bg: #0e1014;
--text: #f2efe8;
}
button {
background: var(--text);
color: var(--bg);
border: 0;
padding: 8px 14px;
border-radius: 8px;
}Line-by-line explanation
- Lines 2 to 4The light theme values.
- Lines 5 to 6Everything reads colours from variables.
- Lines 13 to 16The dark class only redefines the variables.
- Lines 19 to 20Even the button inverts automatically.
Common CSS Variables Mistakes
Forgetting the dashes or var()
:root { brand: blue; }
h1 { color: --brand; }:root { --brand: blue; }
h1 { color: var(--brand); }Using variables in media query conditions
:root { --tablet: 768px; }
@media (min-width: var(--tablet)) { … }@media (min-width: 768px) { … }Variables work in property values, not in media query conditions or selectors.
CSS Variables in Real Projects
Design tokens
Large companies call these "design tokens": a single list of colours, spacing, radii and shadows shared across websites and mobile apps. This website runs on CSS variables. Look for --brand, --ink and --surface in DevTools, and watch them change when you switch to dark mode.
CSS Variables Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Define a variable and use it.
:root {
: #f0592b;
}
.link {
color: ;
}
--name, read with var(--name).Where should you put global variables?
:root is the top of the document, so everything inherits from it.What does var(--size, 16px) do if --size doesn't exist?
The card variables aren't working. Fix the definition and usage so the card has a #e1e6ff background and 20px padding.
<div class="card">Variables are neat</div>:root {
card-bg: #e1e6ff;
--card-pad = 20px;
}
.card {
background: var(card-bg);
padding: --card-pad;
}- Background comes through
- Padding is 20px
- Uses variables
CSS Variables Quiz
3 questions to check what you learned.
CSS custom property names must start with…
- $
- @
- #
- --
Can you change a CSS variable's value inside a specific class?
- No, variables are global constants
- Only with JavaScript
- Only in :root
- Yes, and its children see the new value
Which JavaScript changes a root variable?
document.documentElement.style.setProperty('--brand', 'red')document.css('--brand', 'red')root.brand = 'red'var('--brand') = 'red'
CSS Variables Challenge
Build a tiny design system
- On
:root, define--primary: #7c3aed,--space: 12pxand--round: 10px .tagusesvar(--primary)for itsbackground,var(--space)for horizontal padding andvar(--round)for its radius.tag.warnoverrides only--primaryto#f0592b
<span class="tag">design</span>
<span class="tag warn">deprecated</span>.tag { display: inline-block; color: white; padding-top: 4px; padding-bottom: 4px; font: 600 14px sans-serif; }
- Root variables defined
- Tag is purple
- Tag padding uses --space
- Tag radius is 10px
- Warn tag is orange through the variable