Skip to main content

CSS Custom Properties (Variables)

CSS Custom Properties (often referred to as CSS Variables) are entities defined by CSS authors that contain specific values to be reused throughout a document. Unlike traditional preprocessor variables (Sass/Less), CSS variables live in the DOM, adhere to the cascade, inherit values across elements, and can be read or mutated dynamically at runtime using JavaScript.

1. Syntax, Scoping, and Fallbacks

CSS Custom Properties are declared using a double-hyphen prefix (--) and accessed using the var() function.

Global vs. Local Scoping

  • Global Scope (:root): Properties declared on the :root pseudo-class are available everywhere in the DOM tree.
  • Local Scope: Properties declared inside a specific component selector are scoped strictly to that element and its descendants.
/* Global Scope */
:root {
--primary-color: #2563eb;
--base-padding: 1rem;
}

/* Local Scope Override */
.card-featured {
--primary-color: #d97706; /* Overrides global value for this box & children */
padding: var(--base-padding);
border: 2px solid var(--primary-color);
}

Fallback Values in var()

The var() function accepts a second argument as a fallback value in case the target custom property is undefined:

.button {
/* Uses --button-bg if defined; falls back to #059669 if undefined */
background-color: var(--button-bg, #059669);

/* Nested fallback chain */
color: var(--button-text, var(--primary-color, #ffffff));
}

2. Dynamic Runtime Manipulation with JavaScript

Because custom properties are live DOM objects, you can easily read, write, and remove them dynamically at runtime via JavaScript.

// Get an element reference
const root = document.documentElement;

// Read custom property value
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');

// Dynamically mutate property value
root.style.setProperty('--primary-color', '#10b981');

// Remove custom property override
root.style.removeProperty('--primary-color');

3. Practical Architecture: Theme Switching System

CSS variables enable clean, light/dark theme switching without repeating stylesheet rules. By altering dataset attributes or class names on <html> or <body>, custom property values switch instantly across the UI.

/* Base Theme Tokens */
:root {
--bg-color: #ffffff;
--text-color: #0f172a;
--card-bg: #f8fafc;
--accent-color: #2563eb;
}

/* Dark Theme Overrides */
[data-theme="dark"] {
--bg-color: #0f172a;
--text-color: #f8fafc;
--card-bg: #1e293b;
--accent-color: #38bdf8;
}

/* Components consume variables seamlessly */
body {
background-color: var(--bg-color);
color: var(--text-color);
}

.card {
background-color: var(--card-bg);
border: 1px solid var(--accent-color);
}

Interactive Playground: Dynamic Theme Engine

Test local variable scoping and live custom property toggling in the interactive editor below:

Loading Interactive Editor...

Summary Reference Table

Concept / FeatureSyntax ExampleKey Advantage
Declaration--accent: #2563eb;Establishes a reusable CSS variable
Usagecolor: var(--accent);References variable value with inheritance support
Fallbackvar(--accent, #000000)Provides safe default if variable is undefined
Global Scope:root { --gap: 1rem; }Makes property available across the entire document
JavaScript APIel.style.setProperty('--gap', '2rem')Allows real-time dynamic design token manipulation