CSS Variables (Custom Properties) let you store and reuse values. Define them in :root for global scope, or in selectors for local scope. Change one variable, and everything updates.

Declaring Variables

Define custom properties with --variable-name: value. Convention uses two dashes. Define in :root for global availability.

:root {
  --primary: #1e78a8;
  --primary-dark: #145b7d;
  --spacing: 1rem;
  --border-radius: 8px;
  --transition-speed: 0.3s;
}

body {
  font-size: var(--font-size-base);
  color: var(--text-color);
}

Try it - Check your browser's color scheme

Primary Color
Dark Variant
Accent Color

Using Variables

Reference variables with var(--variable-name). Use anywhere a normal CSS value would go: colors, sizes, spacing, etc.

/* Define */
:root {
  --primary: #1e78a8;
  --padding: 1.5rem;
}

/* Use */
.button {
  background: var(--primary);
  padding: var(--padding);
  border-radius: var(--border-radius);
  transition: all var(--transition-speed);
}

Try it - Consistent styling with variables

Card with Variables

Padding, border, and spacing all use CSS variables.

Variable Scoping

Variables defined in :root are global. Define in selectors for local scope. Child elements inherit parent variables.

/* Global */
:root {
  --primary: blue;
}

/* Local to .container */
.container {
  --primary: green; /* overrides global in this scope */
}

/* Local to .dark-theme */
.dark-theme {
  --bg: #1f2937;
  --text: #ffffff;
}

/* Children inherit */
.container .button {
  background: var(--primary); /* uses local green */
}

Try it - Different color scopes

Global Scope
Local Scope

Fallback Values

Provide fallback values if a variable isn't set. var(--variable, fallback-value). Useful for browser compatibility.

/* If --custom doesn't exist, use red */
.box {
  background: var(--custom, red);
}

/* Multi-level fallback */
.text {
  color: var(--heading-color, var(--text-color, black));
}

/* Fallback with calculation */
.padding {
  padding: var(--padding, 1rem);
  margin: var(--margin, calc(var(--padding, 1rem) * 2));
}

Try it - Fallback example

Has variable (blue)
No variable (fallback: red)

JavaScript Integration

Change CSS variables dynamically with JavaScript. Get and set values with getPropertyValue() and setProperty().

const root = document.documentElement;

/* Get a variable */
const color = root.style.getPropertyValue('--primary');

/* Set a variable */
root.style.setProperty('--primary', '#ff0000');

/* Theme switcher */
document.querySelectorAll('[data-theme]').forEach((btn) => {
  btn.addEventListener('click', function() {
    root.style.setProperty('--primary', this.dataset.color);
  });
});

Try it - Change colors dynamically

CSS Variables vs Preprocessor Variables

Feature CSS Variables SASS/LESS
Runtime Changes ✅ Yes (dynamic) ❌ No (compile-time)
JavaScript Access ✅ Yes ❌ No
Media Queries ✅ Yes (can override in MQ) ❌ No
Inheritance ✅ Yes ❌ No
Math Operations ✅ calc() ✅ Native
Browser Support ✅ All modern browsers ✅ Compiled to CSS

Summary

  • Define CSS variables with --name: value in any selector.
  • :root provides global scope for application-wide variables.
  • var(--name) retrieves variable values.
  • Fallbacks: var(--name, fallback) provides defaults.
  • Inheritance: Child elements inherit parent variables.
  • Dynamic: Change variables with JavaScript at runtime.
  • Theme switching: Perfect use case for CSS variables.
  • calc(): Combine variables in calculations.