Turning Learners Into Developers
Codekilla
CODEKILLA
CSS 8 min

Complete Guide to CSS Variables with Examples

Read on to explore complete guide to css variables with examples — a beginner-friendly walkthrough by Codekilla.

Rahul Chaudhary Thu Apr 30 2026
What Are CSS Variables?

CSS Variables (officially called CSS Custom Properties) let you store values in one place and reuse them throughout your stylesheet. Think of them as containers that hold colors, sizes, spacing, or any CSS value you want to reference multiple times. Instead of typing #3498db fifty times across your CSS, you define it once as --primary-color: #3498db; and call it with var(--primary-color) wherever you need it. They're scoped to elements, which means you can create global variables on :root or local ones that only apply to specific components.

Unlike preprocessor variables from Sass or Less that compile away, CSS Variables are live in the browser. You can change them with JavaScript, respond to media queries, and even inherit them through the DOM tree. This makes them incredibly powerful for theming, responsive design, and dynamic UI updates.

Why It Matters
  • Maintainability: Change your primary brand color in one place, and it updates everywhere instantly — no find-and-replace gymnastics.
  • JavaScript Integration: Toggle dark mode, adjust font sizes for accessibility, or create interactive color pickers by modifying variables in real-time.
  • Scoping Power: Define global defaults on :root, then override them for specific components without touching the original values.
  • Responsive Design: Swap values in media queries without duplicating entire rule blocks — perfect for fluid typography and adaptive spacing.
  • Performance: Browsers handle them natively, no preprocessor compilation required, and they cascade naturally through the CSS inheritance model.
Declaring and Using CSS Variables

You declare CSS Variables using the -- prefix inside any selector. For global variables, use the :root pseudo-class (which targets the document root). To use a variable, wrap it in the var() function.

css
:root {
  --brand-color: #e74c3c;
  --spacing-unit: 1rem;
  --font-main: 'Inter', sans-serif;
}

.button {
  background-color: var(--brand-color);
  padding: var(--spacing-unit);
  font-family: var(--font-main);
}

.card {
  margin-bottom: calc(var(--spacing-unit) * 2);
}

The var() function accepts a second argument as a fallback: var(--unknown-color, #333) returns #333 if --unknown-color isn't defined. You can also nest variables and use them in calc() for mathematical operations.

Scoping: Global vs. Local Variables

CSS Variables respect the cascade and inheritance. Variables defined on :root are globally accessible. Variables defined on specific selectors only exist within that element and its children.

ScopeSelectorAccessibility
Global:root or htmlAvailable everywhere in the document
LocalAny element (.card, #header)Only within that element and descendants
OverrideChild elementInherits parent value unless redefined
css
:root {
  --text-color: #2c3e50;
}

.dark-section {
  --text-color: #ecf0f1; /* Override for this section */
}

p {
  color: var(--text-color); /* Uses global or overridden value */
}

In this example, paragraphs inside .dark-section get light text, while paragraphs elsewhere use the global dark color. This scoping behavior is what makes CSS Variables superior to preprocessor variables for component-based design.

Dynamic Updates with JavaScript

This is where CSS Variables shine. You can manipulate them with JavaScript to create themes, sliders, or user preferences without touching inline styles.

javascript
// Get the root element
const root = document.documentElement;

// Read a variable
const primaryColor = getComputedStyle(root).getPropertyValue('--brand-color');

// Set a variable
root.style.setProperty('--brand-color', '#9b59b6');

// Dark mode toggle example
const toggleDarkMode = () => {
  const isDark = root.style.getPropertyValue('--bg-color') === '#1a1a1a';
  root.style.setProperty('--bg-color', isDark ? '#ffffff' : '#1a1a1a');
  root.style.setProperty('--text-color', isDark ? '#333333' : '#f0f0f0');
};

This approach keeps your styles in CSS where they belong, while JavaScript handles only the logic. No more cluttered inline style="" attributes scattered across your markup.

Responsive Design Patterns

You can redefine variables inside media queries to create adaptive layouts without duplicating property declarations.

css
:root {
  --container-width: 90%;
  --font-size-base: 16px;
  --grid-gap: 1rem;
}

@media (min-width: 768px) {
  :root {
    --container-width: 720px;
    --font-size-base: 18px;
    --grid-gap: 1.5rem;
  }
}

@media (min-width: 1200px) {
  :root {
    --container-width: 1140px;
    --font-size-base: 20px;
    --grid-gap: 2rem;
  }
}

.container {
  width: var(--container-width);
  font-size: var(--font-size-base);
}

.grid {
  gap: var(--grid-gap);
}

Notice how .container and .grid rules stay clean. You only adjust the variable values at breakpoints, not entire rule sets. This dramatically reduces code duplication.

Theming Systems

CSS Variables make multi-theme systems trivial. Define theme palettes, then swap them by changing a single class on the <body> or :root.

css
:root {
  /* Default light theme */
  --bg-primary: #ffffff;
  --bg-secondary: #f8f9fa;
  --text-primary: #212529;
  --text-secondary: #6c757d;
  --accent: #007bff;
}

[data-theme="dark"] {
  --bg-primary: #1a1a1a;
  --bg-secondary: #2d2d2d;
  --text-primary: #e0e0e0;
  --text-secondary: #a0a0a0;
  --accent: #4dabf7;
}

body {
  background-color: var(--bg-primary);
  color: var(--text-primary);
}

.sidebar {
  background-color: var(--bg-secondary);
}

.link {
  color: var(--accent);
}

Toggle themes with JavaScript: document.documentElement.setAttribute('data-theme', 'dark'). Every element using those variables updates instantly.

Quick Cheat Sheet
NeedReach For
Global values used everywhere:root { --var-name: value; }
Component-specific overrides.component { --var-name: value; }
Fallback if variable undefinedvar(--var-name, fallback-value)
Math with variablescalc(var(--spacing) * 2)
Read variable in JSgetComputedStyle(el).getPropertyValue('--var')
Set variable in JSelement.style.setProperty('--var', 'value')
Responsive variable changesRedefine inside @media queries
Theme switchingChange data-theme attribute, define theme palettes
Common Mistakes
  • Using variables without the var() function: Writing color: --brand-color; doesn't work. You must use color: var(--brand-color);.
  • Forgetting the -- prefix: Variable names must start with two dashes. --primary-color works, primary-color doesn't.
  • Expecting them to work like preprocessor variables: CSS Variables are case-sensitive and don't support operations outside calc(). You can't do --spacing * 2 directly.
  • Not providing fallbacks for critical values: If a variable is undefined and you don't provide a fallback, the property becomes invalid and won't render.
  • Over-nesting variable definitions: Defining too many local scopes can make debugging difficult. Keep global defaults on :root and override sparingly.
  • Assuming full browser support for ancient versions: CSS Variables work in all modern browsers but fail in IE11. Use feature detection or fallbacks if supporting legacy environments.

💡 Think Like a Programmer: Treat CSS Variables like you'd treat constants in JavaScript — define them once, use them everywhere, and let the cascade do the heavy lifting. Your future self will thank you when refactoring themes or adjusting spacing systems.

// was this useful?
Did this article answer your question?
// CSS · published by Codekilla
// related articles

Keep Reading