CSS variables, also called custom properties, let you name important design values such as colors, spacing, shadows, and component sizes. The browser keeps them live, so changing one variable can update many rules instantly.
They are especially helpful for themes and component variants. A card can define its own accent color, a dark theme can override global colors, and a media query can adjust spacing values without rewriting every selector.
Add one worked example that compares the normal path with the boundary case for CSS Variables Custom Properties var.
CSS Variables Custom Properties var should be studied as a practical CSS lesson, not as a label. Start by naming the input, the rule that changes the input, and the result a learner should be able to predict after reading the page.
In the css > css-variables page, the notes should connect the definition with a working scenario, a mistake that beginners actually make, and the exact check that proves the fix. That makes the topic useful for coding, debugging, and interview revision.
CSS Variables (officially called Custom Properties) let you store values that can be reused throughout your stylesheet. They are defined with --name and accessed with var(--name). Unlike preprocessor variables (Sass, Less), CSS variables are live - they can be changed at runtime with JavaScript and respond to media queries.
/* Define variables in :root - available globally */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--danger-color: #e74c3c;
--text-color: #2c3e50;
--bg-color: #ecf0f1;
--font-main: 'Roboto', sans-serif;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--border-radius: 4px;
--transition-speed: 0.3s;
}
/* Use variables with var() */
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
}
.btn-primary {
background-color: var(--primary-color);
padding: var(--spacing-md);
border-radius: var(--border-radius);
transition: all var(--transition-speed);
}
.btn-primary:hover {
background-color: var(--secondary-color);
}
/* Fallback value - used if variable is not defined */
.card {
border: 1px solid var(--border-color, #ddd);
}
/* Scoped variables - override in specific contexts */
.dark-theme {
--bg-color: #1a1a2e;
--text-color: #eee;
--primary-color: #64b5f6;
}
/* Calculations with variables */
.container {
padding: calc(var(--spacing-md) * 2); /* 32px */
margin-top: calc(var(--spacing-lg) + 10px); /* 34px */
}
Variables follow normal CSS inheritance. A value defined on :root is available everywhere, but a value defined on .pricing-card applies only to that element and its children. This makes them useful for local component customization.
/* Light theme (default) */
:root {
--bg: #ffffff;
--text: #2c3e50;
--card-bg: #f8f9fa;
--border: #dee2e6;
}
/* Dark theme - override variables */
[data-theme="dark"] {
--bg: #1a1a2e;
--text: #eee;
--card-bg: #16213e;
--border: #0f3460;
}
/* Use variables everywhere */
body {
background-color: var(--bg);
color: var(--text);
transition: background-color 0.3s, color 0.3s;
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--border);
}
// Toggle theme
const toggleBtn = document.getElementById('theme-toggle');
toggleBtn.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
});
// Load saved theme
const saved = localStorage.getItem('theme');
if (saved) document.documentElement.setAttribute('data-theme', saved);
Instead of creating many modifier classes that repeat full declarations, define the parts that change as variables. The component keeps its structure, while each variant changes only the custom properties it owns.
.button {
--button-bg: #2563eb;
--button-text: #ffffff;
--button-border: #2563eb;
background: var(--button-bg);
color: var(--button-text);
border: 1px solid var(--button-border);
padding: 0.75rem 1rem;
border-radius: 0.5rem;
}
.button.secondary {
--button-bg: #ffffff;
--button-text: #2563eb;
}
.button.danger {
--button-bg: #dc2626;
--button-border: #dc2626;
}
CSS Variables Custom Properties var matters in CSS because it changes how a program is written, tested, or debugged. The page should explain the normal flow first: what the developer writes, what the runtime or platform does, and what result should appear.
When teaching CSS Variables Custom Properties var, avoid stopping at syntax. Show the surrounding decision: why this feature is chosen, what problem it removes, and what would become harder if the feature were not used.
.lesson-box {
display: block;
max-width: 42rem;
padding: 1rem;
}
.lesson-box:empty::before {
content: "CSS Variables Custom Properties var: add visible content";
}
Naming a variable --blue when it represents the primary brand color.
Use --color-primary so the name still makes sense if the color changes later.
Defining every variable globally even when only one component uses it.
Place component-only variables on the component selector.
Using var(--space-large) without a fallback when the variable is optional.
Use var(--space-large, 2rem) for a safe default.
Memorizing CSS Variables Custom Properties var without the situation where it is useful.
Connect CSS Variables Custom Properties var to a concrete CSS task.
No. Sass variables are compiled before the browser sees the CSS. CSS variables exist in the browser and can change at runtime.
Yes. JavaScript can call document.documentElement.style.setProperty("--name", value) to update a variable.
You cannot use them as media query conditions, but you can redefine variable values inside a media query.
Check spelling, scope, inheritance, and whether the final value is valid for that CSS property.
Explore 500+ free tutorials across 20+ languages and frameworks.