CSS Variables
CSS variables — officially called CSS Custom Properties — let you store values in one place and reuse them throughout your stylesheet. Change the value in one spot and every element that uses it updates automatically. They work like search-and-replace, except they update live in the browser.
The Problem They Solve
DIAGRAM — Without CSS Variables:
/* Your brand color used 15 different times */
h1 { color: #3498db; }
.btn { background: #3498db; }
.link { border-bottom: 2px solid #3498db; }
.icon { fill: #3498db; }
/* ... 11 more places ... */
Client says: "Change the blue to green."
You manually search and update all 15 spots.
One missed spot = inconsistent design.
DIAGRAM — With CSS Variables:
:root { --brand-color: #3498db; }
h1 { color: var(--brand-color); }
.btn { background: var(--brand-color); }
.link { border-bottom: 2px solid var(--brand-color); }
Client says: "Change the blue to green."
You update ONE line. Done.
Declaring a CSS Variable
Variable names start with two dashes (--). They are declared like a regular CSS property.
:root {
--primary-color: #3498db;
--font-size-base: 16px;
--spacing-md: 24px;
--border-radius: 8px;
}
:root is the recommended place for global variables because it targets the <html> element — the highest point in the page. Variables declared here are available everywhere on the page.
Using a CSS Variable
Use the var() function to apply a variable.
h1 {
color: var(--primary-color);
font-size: var(--font-size-base);
margin-bottom: var(--spacing-md);
}
.card {
border-radius: var(--border-radius);
padding: var(--spacing-md);
border: 1px solid var(--primary-color);
}
Fallback Values
The var() function accepts a second argument — a fallback value used if the variable is not defined.
p {
color: var(--text-color, black);
/* If --text-color is not set, use black */
}
.btn {
padding: var(--btn-padding, 12px 24px);
}
Fallbacks are useful when you build components that others will use — they ensure the component looks reasonable even if the consumer forgets to set a variable.
Variable Scope — Local vs Global
CSS variables follow scope rules. A variable declared on an element is only available to that element and its children.
DIAGRAM — Variable Scope:
:root {
--color: blue; ← Available everywhere on the page
}
.card {
--color: green; ← Only available inside .card and its children
}
.card p { color: var(--color); } → green
main p { color: var(--color); } → blue
:root {
--gap: 16px;
}
.sidebar {
--gap: 8px; /* Override just for sidebar */
}
.sidebar .item {
margin: var(--gap); /* 8px — uses the nearest defined value */
}
.main .item {
margin: var(--gap); /* 16px — falls back to :root */
}
CSS Variables Are Case-Sensitive
:root {
--Color: red;
--color: blue;
}
p { color: var(--Color); } /* red */
h2 { color: var(--color); } /* blue */
/* These are TWO different variables! */
Using Variables Inside Calculations
CSS variables work inside calc(), which lets you do math with them.
:root {
--base-size: 8px;
}
.box {
padding: calc(var(--base-size) * 2); /* 16px */
margin: calc(var(--base-size) * 3); /* 24px */
}
Theming with CSS Variables
CSS variables are the standard way to build light/dark themes. You declare one set of values for light mode and another for dark mode.
/* Light theme (default) */
:root {
--bg: #ffffff;
--text: #111111;
--accent: #3498db;
}
/* Dark theme */
[data-theme="dark"] {
--bg: #1a1a1a;
--text: #f0f0f0;
--accent: #5dade2;
}
body {
background-color: var(--bg);
color: var(--text);
}
a { color: var(--accent); }
JavaScript can then toggle the theme by switching the data-theme attribute on the <html> element — no CSS class changes needed for every individual element.
Changing Variables with JavaScript
CSS variables are readable and writable by JavaScript, making them a bridge between your styles and your scripts.
// Read a variable
const color = getComputedStyle(document.documentElement)
.getPropertyValue('--primary-color');
// Change a variable
document.documentElement.style
.setProperty('--primary-color', '#e74c3c');
// Now every element using --primary-color updates instantly
Building a Spacing Scale
A spacing scale is a set of related sizes. CSS variables make it easy to keep spacing consistent across an entire page.
:root {
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 32px;
--space-xl: 64px;
}
.card {
padding: var(--space-md);
margin-bottom: var(--space-lg);
}
.badge {
padding: var(--space-xs) var(--space-sm);
}
What CSS Variables Cannot Do
- They cannot be used as property names:
var(--prop): value— invalid. - They do not work in media query conditions:
@media (max-width: var(--breakpoint))— invalid. - They cannot contain a semicolon inside their value unless you use IDENT tokens.
CSS Variables vs Preprocessor Variables
| Feature | CSS Variables | Sass/Less Variables |
|---|---|---|
| Runs in browser | Yes | No — compiled to CSS |
| Live updates via JS | Yes | No |
| Scope-aware | Yes — cascade-based | No — file-scoped |
| Works in DevTools | Yes | No |
| Browser support | All modern browsers | Compiled, universal |
CSS variables are one of the most powerful tools in modern CSS. Start with a small token system — colors, spacing, and font sizes — declared in :root, and use them consistently. This habit alone makes maintenance dramatically easier on any project.
