A
AiTechWorlds
AiTechWorlds
CSS custom properties (commonly called CSS variables) let you define reusable values in one place and reference them throughout your stylesheet. Combined with JavaScript, they enable dynamic theming, dark mode, and runtime style changes.
/* Define on :root — globally available */
:root {
--color-primary: #4a90e2;
--color-secondary: #6c757d;
--color-background: #ffffff;
--color-text: #1a1a2e;
--color-error: #e74c3c;
--color-success: #2ecc71;
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--spacing-xl: 4rem;
--font-size-sm: 0.875rem;
--font-size-md: 1rem;
--font-size-lg: 1.25rem;
--font-size-xl: 1.5rem;
--font-size-2xl: 2rem;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
--radius-full: 999px;
--shadow-sm: 0 1px 3px rgba(0,0,0,0.12);
--shadow-md: 0 4px 12px rgba(0,0,0,0.15);
--shadow-lg: 0 8px 30px rgba(0,0,0,0.20);
--transition: 200ms ease;
}
/* Use with var() */
.button {
background-color: var(--color-primary);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
font-size: var(--font-size-md);
transition: background-color var(--transition);
}
.button:hover {
background-color: var(--color-secondary);
}
/* var(--property, fallback) */
.element {
color: var(--text-color, #333); /* use #333 if --text-color isn't set */
font-size: var(--size, var(--font-size-md, 1rem)); /* chained fallbacks */
}
:root {
--bg: #ffffff;
--text: #1a1a2e;
--card-bg: #f8f9fa;
--border: #e0e0e0;
}
/* Option 1: Using prefers-color-scheme */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a2e;
--text: #e8e8f0;
--card-bg: #2d2d44;
--border: #404060;
}
}
/* Option 2: Using data attribute (user-toggled) */
[data-theme="dark"] {
--bg: #1a1a2e;
--text: #e8e8f0;
--card-bg: #2d2d44;
--border: #404060;
}
/* Use variables throughout */
body {
background-color: var(--bg);
color: var(--text);
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--border);
}
// Toggle dark mode via JavaScript
const toggle = document.getElementById("theme-toggle");
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
let isDark = prefersDark.matches;
function applyTheme() {
document.documentElement.dataset.theme = isDark ? "dark" : "light";
toggle.textContent = isDark ? "☀️" : "🌙";
}
toggle.addEventListener("click", () => {
isDark = !isDark;
localStorage.setItem("theme", isDark ? "dark" : "light");
applyTheme();
});
// Apply saved preference
const saved = localStorage.getItem("theme");
if (saved) isDark = saved === "dark";
applyTheme();
Override variables for specific components:
.button {
--btn-bg: var(--color-primary);
--btn-text: white;
--btn-padding: var(--spacing-sm) var(--spacing-md);
background: var(--btn-bg);
color: var(--btn-text);
padding: var(--btn-padding);
}
.button--danger {
--btn-bg: var(--color-error); /* just override the variable */
}
.button--large {
--btn-padding: var(--spacing-md) var(--spacing-lg);
}
/* No need to rewrite all button properties */
:root {
--primary-hue: 210; /* just the hue, update this one value */
--color-primary: hsl(var(--primary-hue), 70%, 50%);
--color-primary-light: hsl(var(--primary-hue), 70%, 70%);
--color-primary-dark: hsl(var(--primary-hue), 70%, 30%);
}
// Read a CSS variable
const hue = getComputedStyle(document.documentElement)
.getPropertyValue("--primary-hue").trim();
// Set a CSS variable
document.documentElement.style.setProperty("--primary-hue", "280");
// Now ALL colors derived from --primary-hue update instantly!
// Color picker that updates the whole theme
colorPicker.addEventListener("input", (e) => {
document.documentElement.style.setProperty("--primary-hue", e.target.value);
});
:root {
--animation-speed: 200ms;
}
.card {
transform: translateY(0);
transition: transform var(--animation-speed) ease;
}
.card:hover {
transform: translateY(-4px);
}
/* User can prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
:root { --animation-speed: 0ms; }
}
Next lesson: Animations & Transitions — bringing your UI to life.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises