DevLab
CSS

CSS Custom Properties (Variables) Explained

Learn how CSS custom properties work, how they differ from preprocessor variables, and how to use them for theming, dark mode, and dynamic styling.

What are CSS Custom Properties?

CSS custom properties (CSS variables) store values in named variables and let you reuse them across your stylesheet. Unlike Sass variables (replaced at compile time), CSS custom properties are live in the browser — changeable by JavaScript, overridable per-element, and responsive to media queries.

Syntax

/* Define on :root to make globally available */
:root {
  --color-primary: #3b82f6;
  --spacing-base: 16px;
  --border-radius: 8px;
}

/* Use with var() — optional fallback after the comma */
.button {
  background-color: var(--color-primary);
  padding: var(--spacing-base);
  color: var(--color-text, #333);  /* #333 if --color-text is unset */
}

Dark Mode Theming

:root {
  --bg: #ffffff;
  --text: #111827;
}

@media (prefers-color-scheme: dark) {
  :root { --bg: #111827; --text: #f9fafb; }
}

/* Or toggle with a class */
[data-theme="dark"] { --bg: #111827; --text: #f9fafb; }

JavaScript Access

// Read
const color = getComputedStyle(document.documentElement)
  .getPropertyValue('--color-primary').trim();

// Write — updates instantly across the whole page
document.documentElement.style.setProperty('--color-primary', '#ef4444');

// Apply saved user preference from localStorage
const saved = localStorage.getItem('accent-color');
if (saved) document.documentElement.style.setProperty('--color-primary', saved);

Component-Scoped Variables

/* Scope to a component */
.card {
  --card-shadow: 0 1px 3px rgba(0,0,0,0.1);
  box-shadow: var(--card-shadow);
}

/* Override for a variant without an extra class */
.card.card--elevated {
  --card-shadow: 0 10px 25px rgba(0,0,0,0.15);
}

CSS Variables vs Sass Variables

Sass $variable is replaced at compile time — the output CSS has just the value. CSS custom properties exist at runtime, so they cascade, inherit, can be overridden per-element, and changed by JavaScript. Use Sass for build-time constants like breakpoints in @media queries (which cannot use CSS variables). Use CSS custom properties for everything that should be themeable or dynamic.

More Learning Topics