CSS Custom Properties In-Depth Overview & Use Cases

CSS Custom Properties (commonly referred to as CSS Variables) bring dynamic values directly into native stylesheets without needing Sass or Less preprocessors. Custom properties start with a double dash (e.g. --brand-color) and can be accessed anywhere using the var() function.

Unlike preprocessor variables which compile down to static CSS values at build time, native CSS variables live in the DOM cascade. They can be updated dynamically at runtime via JavaScript, overridden inside specific component scopes, or swapped instantly using media queries for Dark Mode themes.

Key Real-World Use Cases
#1Design System Tokens

Defining centralized color palettes, spacing scales, and font stacks on the :root element.

#2Dark Mode Theme Toggling

Swapping surface and text variables when a [data-theme="dark"] attribute is added to the <html> tag.

#3Component Variants

Overriding scoped variables inside card or button modifier classes.

#4Interactive JS Controls

Updating mouse cursor coordinates or scroll percentage variables directly from JavaScript event listeners.

CSS Variables & Theme Tokens Studio
Presets:
Dynamic UI Theme Card
Active Token

CSS Variables enable global theme switches in real time. Changing custom property values repaints components instantly across the DOM cascade without reloading.

Generated CSS Variables
:root { --primary-color: #3b82f6; --bg-surface: #ffffff; --text-main: #0f172a; --radius-md: 12px; --shadow-depth: 0 5px 10px rgba(0, 0, 0, 0.15); } .card-component { background-color: var(--bg-surface); color: var(--text-main); border-radius: var(--radius-md); box-shadow: var(--shadow-depth); } .btn-action { background-color: var(--primary-color); }

Declaring & Using Variables (:root Scope & var())

Custom properties declared on the :root pseudo-class become globally available across the entire document cascade.

Global Variable Declaration & Usage
:root { --primary-color: #2563eb; --bg-surface: #ffffff; --text-main: #0f172a; --spacing-md: 1rem; } .button-primary { /* Using global variable with fallback */ background-color: var(--primary-color, #000000); padding: var(--spacing-md); color: var(--bg-surface); }
The second argument inside var(--name, fallback) acts as a safety default if the variable is not defined.

Light / Dark Mode Theme Switching Pattern

Because CSS variables participate in the cascade, swapping an attribute on <html> or <body> instantly updates all components across the entire website.

Complete Theme Switching CSS Pattern
/* Light Theme Default */ :root { --bg-color: #f8fafc; --text-color: #0f172a; --card-bg: #ffffff; } /* Dark Theme Overrides */ [data-theme="dark"] { --bg-color: #0f172a; --text-color: #f8fafc; --card-bg: #1e293b; } body { background-color: var(--bg-color); color: var(--text-color); }
Changing document.documentElement.setAttribute("data-theme", "dark") dynamically repaints all elements using these custom properties.

Dynamic Control via JavaScript

JavaScript can read and update CSS variables in real time using getPropertyValue() and setProperty():

Updating CSS Variables with JS
// Change primary color dynamically document.documentElement.style.setProperty('--primary-color', '#10b981'); // Read current computed value const currentBg = getComputedStyle(document.documentElement) .getPropertyValue('--bg-color');
Allows building interactive color pickers and mouse-following gradient effects.

Frequently Asked Questions

Sass variables compile down to static CSS values during build time and cannot change in the browser. Native CSS variables exist in the DOM, follow inheritance rules, and update dynamically via JS or media queries.

Yes! --main-color and --Main-Color are treated as two distinct CSS variables.

If no fallback is provided in var(--invalid, fallback), the property reverts to its initial or inherited CSS value.