CSS variables (custom properties) let you store reusable values and create dynamic, maintainable stylesheets.
Defining and Using Variables
CSS
/* Define in :root (available everywhere) */
:root {
--primary: #3b82f6;
--primary-dark: #2563eb;
--text: #1f2937;
--text-light: #6b7280;
--bg: #ffffff;
--bg-surface: #f9fafb;
--border: #e5e7eb;
--radius: 8px;
--shadow: 0 1px 3px rgba(0,0,0,0.1);
--spacing: 16px;
--font-sans: system-ui, -apple-system, sans-serif;
}
/* Use with var() */
.button {
background: var(--primary);
color: white;
border-radius: var(--radius);
padding: var(--spacing);
font-family: var(--font-sans);
}
/* Fallback values */
.element {
color: var(--custom-color, #333); /* Falls back to #333 */
}Scoped Variables
CSS
/* Variables can be scoped to any element */
.card {
--card-bg: white;
--card-padding: 24px;
background: var(--card-bg);
padding: var(--card-padding);
}
.card.dark {
--card-bg: #1f2937; /* Override for dark variant */
}
/* Inherit and override */
.sidebar {
--sidebar-width: 250px;
width: var(--sidebar-width);
}
.sidebar.collapsed {
--sidebar-width: 60px; /* Override */
}Dynamic Theming
CSS
/* Light theme (default) */
:root {
--bg: #ffffff;
--text: #1f2937;
--primary: #3b82f6;
}
/* Dark theme */
[data-theme="dark"] {
--bg: #111827;
--text: #f9fafb;
--primary: #60a5fa;
}
/* High contrast */
[data-theme="high-contrast"] {
--bg: #000000;
--text: #ffffff;
--primary: #ffff00;
}
body {
background: var(--bg);
color: var(--text);
}
a { color: var(--primary); }JavaScript
// Toggle theme with JavaScript
document.documentElement.dataset.theme =
document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';Practical Patterns
CSS
/* Typography scale */
:root {
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
}
body { font-size: var(--text-base); }
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
small { font-size: var(--text-sm); }
/* Spacing scale */
:root {
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
}
.card { padding: var(--space-6); }
.gap { gap: var(--space-4); }
/* Responsive with variables */
:root {
--container-max: 1200px;
--gutter: 16px;
}
@media (min-width: 768px) {
:root {
--gutter: 24px;
}
}
.container {
max-width: var(--container-max);
padding: 0 var(--gutter);
}Knowledge Check
4 questions — test your understanding
1
Where should you define global CSS variables?
2
What does `var(--color, #333)` do if --color is not defined?
3
Can CSS variables be changed dynamically?
4
What is the benefit of a spacing scale using CSS variables?