CSS Custom Properties (Variables)
What are CSS Custom Properties?
CSS Custom Properties, also known as CSS Variables, allow you to define reusable values in your stylesheets. They enable you to store values in one place and reference them throughout your CSS, making maintenance easier and enabling dynamic theming.
Browser Support
CSS Custom Properties are well-supported in modern browsers:
- Chrome 49+
- Firefox 31+
- Safari 9.1+
- Edge 15+
Basic Syntax
Defining Custom Properties
Custom properties must start with --
and are case-sensitive:
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--spacing-unit: 8px;
--font-size-base: 16px;
--border-radius: 4px;
}
Using Custom Properties
Use the var()
function to access custom property values:
.button {
background-color: var(--primary-color);
padding: var(--spacing-unit);
border-radius: var(--border-radius);
}
.card {
margin: var(--spacing-unit);
border: 1px solid var(--secondary-color);
}
Fallback Values
The var()
function accepts a fallback value as its second argument:
.element {
/* If --text-color isn't defined, use #333 */
color: var(--text-color, #333);
/* Multiple fallbacks */
margin: var(--custom-margin, var(--spacing-unit, 1rem));
}
Scope and Inheritance
Custom properties follow standard CSS inheritance rules:
Global Scope
:root {
--brand-color: #ff0000;
}
/* Available everywhere */
body {
color: var(--brand-color);
}
Component Scope
.card {
--card-padding: 1rem;
padding: var(--card-padding);
}
/* Only available within .card */
.card .title {
margin-bottom: var(--card-padding);
}
Dynamic Theming
Light/Dark Theme Example
/* Default light theme */
:root {
--bg-color: #ffffff;
--text-color: #333333;
--border-color: #dddddd;
--accent-color: #0066cc;
}
/* Dark theme */
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #ffffff;
--border-color: #444444;
--accent-color: #66b3ff;
}
/* Apply theme colors */
body {
background-color: var(--bg-color);
color: var(--text-color);
}
.card {
border: 1px solid var(--border-color);
}
.button {
background-color: var(--accent-color);
color: var(--bg-color);
}
Advanced Techniques
Calculations with Custom Properties
:root {
--spacing-unit: 8px;
--container-width: 800px;
--columns: 3;
}
.grid {
/* Calculate column width */
--column-width: calc(var(--container-width) / var(--columns));
--gap: calc(var(--spacing-unit) * 2);
display: grid;
grid-template-columns: repeat(var(--columns), var(--column-width));
gap: var(--gap);
}
Responsive Values
:root {
--responsive-padding: 1rem;
}
@media (min-width: 768px) {
:root {
--responsive-padding: 2rem;
}
}
@media (min-width: 1200px) {
:root {
--responsive-padding: 3rem;
}
}
.container {
padding: var(--responsive-padding);
}
Component Variants
.button {
--button-bg: var(--primary-color);
--button-color: white;
background: var(--button-bg);
color: var(--button-color);
}
.button.secondary {
--button-bg: var(--secondary-color);
}
.button.ghost {
--button-bg: transparent;
--button-color: var(--primary-color);
}
JavaScript Integration
Reading Custom Properties
// Get computed value
const styles = getComputedStyle(document.documentElement);
const primaryColor = styles.getPropertyValue('--primary-color');
// Get inline value
const element = document.querySelector('.element');
const value = element.style.getPropertyValue('--custom-prop');
Setting Custom Properties
// Set on root element
document.documentElement.style.setProperty('--primary-color', '#ff0000');
// Set on specific element
const element = document.querySelector('.element');
element.style.setProperty('--custom-prop', '100px');
Theme Switching Example
function setTheme(theme) {
document.documentElement.dataset.theme = theme;
}
// Toggle between light and dark
const themeToggle = document.querySelector('#theme-toggle');
themeToggle.addEventListener('click', () => {
const currentTheme = document.documentElement.dataset.theme;
setTheme(currentTheme === 'dark' ? 'light' : 'dark');
});
Best Practices
1. Use Meaningful Names
/* ✓ Good */
:root {
--primary-color: #3498db;
--spacing-large: 2rem;
}
/* ✗ Bad */
:root {
--color1: #3498db;
--space: 2rem;
}
2. Organize by Component
/* ✓ Good */
.card {
--card-padding: 1rem;
--card-bg: white;
--card-border: 1px solid #ddd;
padding: var(--card-padding);
background: var(--card-bg);
border: var(--card-border);
}
3. Document Your System
/* Color System */
:root {
/* Primary Colors */
--color-primary-100: #e3f2fd;
--color-primary-500: #2196f3;
--color-primary-900: #0d47a1;
/* Semantic Colors */
--color-text: var(--color-primary-900);
--color-background: white;
--color-accent: var(--color-primary-500);
}
4. Provide Fallbacks
.element {
/* Multiple fallbacks for better browser support */
background-color: #3498db; /* Fallback */
background-color: var(--primary-color, #3498db);
}
Common Use Cases
- Theming Systems: Light/dark modes and brand variations
- Component Libraries: Reusable, customizable components
- Responsive Design: Values that change with breakpoints
- Animation: Dynamic values for transitions and animations
- Layout Systems: Consistent spacing and sizing
CSS Custom Properties are a powerful feature that enables more maintainable, dynamic, and flexible stylesheets. They're essential for modern CSS development and design systems.