CSSApril 2026 ยท 12 min read

CSS Custom Properties (Variables): The Complete Guide

Master CSS custom properties: declare, inherit, scope, fallback values, dark mode theming, and responsive design with native CSS variables.

๐ŸŽ›๏ธ
Try the CSS Variable Generator
Free, no signup
โ†’
DG
Derek Giordano
Designer & Developer
In this guide
01What Are Custom Properties?02Declaring & Using Variables03Scope & Inheritance04Fallback Values05Dark Mode Theming06Responsive Design with Variables07Accessing Variables from JavaScript08CSS Variables vs Sass/LESS09Best Practices
โšก Key Takeaways
  • Master CSS custom properties: declare, inherit, scope, fallback values, dark mode theming, and responsive design with native CSS variables.
  • What Are Custom Properties?.
  • Covers declaring & using variables.
  • Covers scope & inheritance.
  • Covers fallback values.

What Are Custom Properties?

CSS custom properties โ€” commonly called CSS variables โ€” let you store values in one place and reference them throughout your stylesheet. They're native to the browser, require no build step, and support features that preprocessor variables can't match: cascade, inheritance, runtime changes, and JavaScript interaction.

Custom properties were a missing piece in CSS for over a decade. Sass and LESS filled the gap with compile-time variables, but those variables vanish after the build โ€” they can't be changed at runtime, don't cascade through the DOM, and can't be read or modified with JavaScript. CSS custom properties solve all three problems.

Declaring & Using Variables

Declare a custom property with a double-hyphen prefix. Reference it with the var() function:

๐Ÿ’ก Tip
CSS Grid auto-fill and auto-fit behave differently when there are fewer items than columns. Use auto-fill to keep empty tracks; auto-fit to collapse them.
:root {\n --color-primary: #3B82F6;\n --spacing-md: 16px;\n --font-body: 'DM Sans', sans-serif;\n}\n\n.button {\n background: var(--color-primary);\n padding: var(--spacing-md);\n font-family: var(--font-body);\n}

The :root selector targets the element, making these variables available everywhere in the document. You can also declare variables on any element to limit their scope.

Scope & Inheritance

Custom properties follow the same cascade and inheritance rules as any CSS property. A variable declared on a parent element is available to all its children. A variable declared on a more specific selector overrides the inherited value within that subtree.

โš  Warning
Avoid animating width, height, top, or left. These trigger layout recalculations on every frame and can drop performance below 60fps.
:root { --bg: #ffffff; }\n.dark-section { --bg: #0B0D17; }\n.card { background: var(--bg); }

A .card inside .dark-section uses the dark background; a .card outside it uses white. This scoping behavior is what makes CSS variables so powerful for theming โ€” you change the variable at a container level and everything inside adapts automatically.

Variables declared on a pseudo-class like :hover or :focus apply only when that state is active, enabling dynamic state-driven styling without JavaScript.

Fallback Values

The var() function accepts a second argument as a fallback value. If the variable isn't defined in the current scope, the fallback is used:

color: var(--text-color, #333333);

Fallbacks can also reference other variables:

color: var(--theme-text, var(--default-text, black));

This chaining pattern is useful for component libraries where a consumer might or might not define a theme variable. The component uses the theme variable if present, falls back to its own default, and uses a safe final value as a last resort.

Dark Mode Theming

CSS custom properties make dark mode implementation clean and maintainable. Define your color palette as variables, then override them inside a prefers-color-scheme media query or a .dark class:

:root {\n --bg: #ffffff;\n --text: #1a1a2e;\n --surface: #f5f5f5;\n --border: rgba(0, 0, 0, 0.1);\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --bg: #0B0D17;\n --text: #E8E8ED;\n --surface: rgba(255, 255, 255, 0.03);\n --border: rgba(255, 255, 255, 0.06);\n }\n}

Every component that references these variables switches themes automatically โ€” no component-level CSS changes needed. This approach scales from a personal blog to a design system with hundreds of components.

Responsive Design with Variables

You can redefine custom properties inside media queries to create responsive systems without duplicating property declarations:

:root {\n --container-padding: 16px;\n --font-size-hero: 28px;\n --grid-columns: 1;\n}\n\n@media (min-width: 768px) {\n :root {\n --container-padding: 32px;\n --font-size-hero: 48px;\n --grid-columns: 2;\n }\n}\n\n@media (min-width: 1200px) {\n :root {\n --container-padding: 64px;\n --font-size-hero: 64px;\n --grid-columns: 3;\n }\n}

Components reference these variables once and adapt at every breakpoint. This dramatically reduces the number of media queries scattered across your stylesheet.

Accessing Variables from JavaScript

Unlike preprocessor variables, CSS custom properties exist at runtime and can be read and written with JavaScript:

// Read a variable\nconst primary = getComputedStyle(document.documentElement)\n .getPropertyValue('--color-primary');\n\n// Write a variable\ndocument.documentElement.style\n .setProperty('--color-primary', '#FF6B6B');

This enables powerful patterns like user-configurable themes, scroll-driven animations, and cursor-following effects โ€” all driven by a single CSS variable that JavaScript updates and CSS consumes.

CSS Variables vs Sass/LESS Variables

Sass and LESS variables are compile-time: they're resolved during the build and replaced with static values. They can't change at runtime, don't respect the DOM cascade, and aren't accessible to JavaScript. But they do support math operations and more complex logic during compilation.

CSS custom properties are runtime: they exist in the browser, cascade through the DOM, and can be changed dynamically. They don't support complex math (though calc() works), and they can't be used in selectors or media query conditions.

In practice, most modern projects use CSS custom properties for theming and design tokens, and preprocessor variables for build-time configuration like breakpoint values and mixin parameters.

Best Practices

Name semantically, not visually. Use `--color-primary` instead of `--blue`. When your brand color changes from blue to purple, semantic names still make sense.

Use a consistent naming convention. Common patterns include `--category-property-variant` (e.g., `--color-text-muted`, `--spacing-lg`) or BEM-style nesting.

Keep `:root` variables to design tokens only. Component-specific variables should be scoped to the component's selector, not polluting the global namespace.

Document your variables. A comment block listing all available variables with their purpose is invaluable for team projects. Or better yet, use the CSS Variable Generator to build and export a documented variable system.

Frequently Asked Questions

What are CSS custom properties?+
CSS custom properties (also called CSS variables) are named values you define in your stylesheet and reference with var(). They cascade through the DOM, can be overridden by scope, and can be changed at runtime with JavaScript โ€” unlike preprocessor variables.
Can I use CSS variables in media queries?+
You can redefine variable values inside media queries, but you cannot use var() in the media query condition itself (e.g., @media (min-width: var(--breakpoint)) won't work). The condition must use a static value.
Do CSS variables work in all browsers?+
CSS custom properties are supported in all modern browsers including Chrome, Firefox, Safari, and Edge. Internet Explorer 11 does not support them. Browser support has been universal since approximately 2017.
What is the var() fallback?+
The var() function accepts an optional second argument that's used if the variable is undefined: var(--color, #333). You can chain fallbacks by nesting var() calls.
Try it yourself

Use the CSS Variable Generator โ€” free, no signup required.

โšก Open CSS Variable Generator
DG
Derek Giordano
Written by the creator of Ultimate Design Tools. BA in Business Marketing.
โšก Try the free Design Token Generator โ†’