What Are CSS Variables?
CSS custom properties, commonly called CSS variables, let you define a reusable value once and reference it throughout your stylesheet using the var() function.
Defining and Using a Variable
<style>
:root {
--brand-color: #764ba2;
--spacing: 16px;
}
.box {
background: var(--brand-color);
padding: var(--spacing);
color: white;
}
</style>
<div class="box">Styled using CSS variables</div>The :root Selector
:root targets the highest-level element in the document (equivalent to <html>, but with slightly higher specificity), making it the conventional place to define variables meant to be used globally.
Fallback Values
var() accepts a second argument as a fallback, used if the variable is not defined: var(--spacing, 10px).
Fallback Value
.box {
/* Uses 10px if --spacing was never defined */
padding: var(--spacing, 10px);
}Scoped Variables
Unlike Sass variables, CSS variables are live and scoped like normal CSS — redefining a variable inside a selector overrides it only for that element and its descendants.
Scoped Override
<style>
:root {
--btn-color: steelblue;
}
.btn {
background: var(--btn-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
margin-right: 8px;
}
.btn.danger {
--btn-color: crimson;
}
</style>
<button class="btn">Default</button>
<button class="btn danger">Danger</button>Updating Variables with JavaScript
Because CSS variables are live, JavaScript can update them at runtime with element.style.setProperty('--brand-color', 'orange') — a common technique for building theme switchers without reloading stylesheets.
Variables vs Preprocessor Variables
Sass/Less variables are compiled away and fixed at build time. CSS variables exist in the browser at runtime, can be changed dynamically, and automatically cascade and inherit like any other CSS value.
Best Practice
Define your design tokens — colors, spacing, font sizes — as CSS variables on :root early in a project. It makes theming, dark mode, and consistent redesigns far easier down the line.