← Back to Blog
CSS 📅 18 Feb 2026 ⏱ 11 min read
🎨

CSS Custom Properties: Variables, Theming, and @property

Runtime theming, JavaScript integration, @property for animated variables, and a complete design token architecture with CSS custom properties.

Why Custom Properties Are Different From Sass Variables

CSS custom properties exist at runtime in the browser's live document model. Unlike Sass variables — which compile away to static values — CSS variables cascade and inherit, can be overridden at any scope level, and are readable and writable from JavaScript. This runtime nature enables capabilities no preprocessor can match.

Declaration and Fallbacks

:root {
  --color-primary: #6366f1;
  --spacing-4: 1rem;
  --radius-md: 12px;
  --font-sans: 'Inter', system-ui, sans-serif;
}
.button {
  background:    var(--color-primary);
  padding:       var(--spacing-4);
  border-radius: var(--radius-md);
}
/* Fallback chain */
.card { color: var(--card-text, var(--text-primary, #1e293b)); }

Scope Override for Component Theming

:root { --accent: #6366f1; }
.theme-teal  { --accent: #14b8a6; }
.theme-amber { --accent: #f59e0b; }
/* All components using var(--accent) automatically adapt */
.btn   { background: var(--accent); }
.badge { border-color: var(--accent); }

Dark Mode in Under 20 Lines

:root {
  --bg: #ffffff; --text: #0f172a; --border: #e2e8f0;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #060b14; --text: #f1f5f9; --border: #1e2d45;
  }
}
body { background: var(--bg); color: var(--text); }

JavaScript Integration

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

// Write globally
document.documentElement.style.setProperty('--color-primary', '#ec4899');

// Write scoped to element
card.style.setProperty('--card-bg', userColor);

@property: Typed and Animated Variables

@property --hue {
  syntax: '<number>';
  initial-value: 220;
  inherits: false;
}
.btn {
  background: hsl(var(--hue), 70%, 55%);
  transition: --hue 0.5s ease;
}
.btn:hover { --hue: 320; } /* smoothly animated */

Three-Tier Design Token Architecture

/* Tier 1: Primitives */
:root { --purple-500: #6366f1; --space-4: 1rem; }
/* Tier 2: Semantic */
:root { --color-interactive: var(--purple-500); }
/* Tier 3: Component */
.button { background: var(--color-interactive); }

With this architecture, a brand colour change takes one line. A full rebrand takes five.

CSS custom properties bridge design and code. When your design tokens are CSS variables, your design system and stylesheet are the same system — one source of truth, zero translation layer.

Share: 𝕏 Twitter in LinkedIn
← Previous
Modern SEO in 2026: What Works and What Google Killed
Next →
Building Accessible Web Components: The Complete WCAG Guide