CSS Custom Properties (Variables)
Master dynamic design tokens, runtime DOM cascade inheritance, JavaScript live mutation, and the modern `@property` API.
1. Real-World Analogy: Live Electrical Power Grid vs Static Drywall
Think of CSS Custom Properties like a modern smart electrical power grid in a high-tech building:
β‘ Dynamic CSS Variables (`var(--token)`)
Like a live electrical grid with adjustable voltage dials. If you turn the master theme dial from light to dark at the breaker box (:root or data-theme), every lamp and device throughout the building adjusts its color instantly in real-time!
πͺ΅ Static Sass/SCSS Variables (`$color`)
Like pre-cut wooden planks. Once the carpenter nails the planks together during the build step (Sass compilation), the wood is fixed in stone. It cannot respond to DOM state changes or user toggles at runtime.
2. Declaration, Scoping & Fallbacks
CSS Variables begin with a double hyphen (--) and are read using the var() function:
/* 1. Global Scope (Available throughout the entire DOM tree) */
:root {
--primary-color: #6C4CE8;
--surface-bg: #FFFFFF;
--base-radius: 8px;
--font-brand: 'Inter', sans-serif;
}
/* 2. Component Scoped Override */
.warning-banner {
--primary-color: #EF4444; /* Re-scopes --primary-color only inside this container */
}
/* 3. Usage with Fallback Value */
.action-btn {
background: var(--btn-accent, var(--primary-color, #0284C7));
border-radius: var(--base-radius);
}
3. CSS Custom Properties vs Sass/Preprocessor Variables
| Feature | Native CSS Variables (`--var`) | Sass / SCSS Variables (`$var`) |
|---|---|---|
| Evaluation Time | π’ Runtime (In the browser) | π΄ Build-time (Compiled to static CSS) |
| DOM Cascade & Inheritance | β Yes (Obeys DOM nesting & media queries) | β No (Static compile-time scoping) |
| JavaScript Manipulation | β
Live read/write via element.style.setProperty() |
β Inaccessible to JavaScript at runtime |
| Media Query Scoping | β
Can redefine values directly inside @media |
β Cannot change variables dynamically in media queries |
4. Interactive Workbench: Dynamic Theme Mutation
Observe how redefining design tokens on a container instantly repaints all child components:
/* 1. Theme Variant Token Defintions */
.theme-light {
--card-bg: #FFFFFF;
--card-text: #0F172A;
--accent-color: #6C4CE8;
--border-color: #E2E8F0;
}
.theme-dark {
--card-bg: #0F172A;
--card-text: #F8FAFC;
--accent-color: #38BDF8;
--border-color: #334155;
}
/* 2. Abstract Component uses Tokens */
.token-card {
background: var(--card-bg);
color: var(--card-text);
border: 1.5px solid var(--border-color);
padding: 16px;
border-radius: 10px;
}
5. Modern `@property` Registration & Gradient Transitions
By default, CSS cannot interpolate custom variables in transitions because it doesn't know their data type. The modern @property rule registers explicit types (<color>, <percentage>, <angle>), enabling smooth gradient animations:
/* Register typed custom property */
@property --gradient-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
.animated-gradient-border {
background: conic-gradient(from var(--gradient-angle), #6C4CE8, #38BDF8, #6C4CE8);
transition: --gradient-angle 0.6s ease;
}
.animated-gradient-border:hover {
--gradient-angle: 180deg; /* Smoothly rotates the conic gradient! */
}
6. CSS Custom Properties Mastery Quiz Deck
Test your knowledge with 5 placement-ready interactive multiple choice questions:
π― Placement Interview Key Takeaways
- Q: Why is `:root` preferred over `html` for declaring global CSS custom properties?
Ans::rootis a pseudo-class that has a higher specificity (0, 0, 1, 0) than thehtmltype selector (0, 0, 0, 1) and matches the top-level document element in any document format (including SVG). - Q: How do you build high-performance dark mode themes using CSS custom properties?
Ans: Define all semantic color tokens in:root, and simply redefine them under[data-theme="dark"]or@media (prefers-color-scheme: dark). When switching themes, zero CSS classes on individual components need to changeβthe browser cascades the token changes instantly! - Q: Can CSS custom properties contain unitless numbers for math?
Ans: Yes! E.g.--gap: 8;and use it ingap: calc(var(--gap) * 1px);. However, you cannot concatenate strings and numbers directly likevar(--gap)px(usecalc()multiplication instead).