CSS Custom Properties, commonly known as CSS variables, have revolutionized how we approach styling in modern web development. They offer a native solution for creating maintainable, dynamic, and scalable stylesheets.
What Are CSS Custom Properties?
Unlike Sass variables, CSS custom properties are:
- Live: They can be changed at runtime
- Inherited: They follow CSS inheritance rules
- Scoped: They can be defined at any level of specificity
Basic Syntax and Usage
Defining Custom Properties
:root {
--primary-color: #3b82f6;
--secondary-color: #1e40af;
--text-color: #1f2937;
--border-radius: 8px;
}
Using Custom Properties
.button {
background-color: var(--primary-color);
color: white;
border-radius: var(--border-radius);
}
.card {
border: 1px solid var(--primary-color);
border-radius: var(--border-radius);
}
Advanced Techniques
Dynamic Theming
One of the most powerful applications is creating dynamic themes:
/* Light theme */
:root {
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--text-primary: #1f2937;
--text-secondary: #6b7280;
}
/* Dark theme */
:root.dark {
--bg-primary: #111827;
--bg-secondary: #1f2937;
--text-primary: #f9fafb;
--text-secondary: #d1d5db;
}
Responsive Design with Custom Properties
:root {
--container-padding: 1rem;
--font-size-large: 2rem;
}
@media (min-width: 768px) {
:root {
--container-padding: 2rem;
--font-size-large: 3rem;
}
}
.container {
padding: var(--container-padding);
}
.headline {
font-size: var(--font-size-large);
}
Component-Scoped Variables
.progress-bar {
--progress-width: 0%;
--progress-color: #10b981;
width: 100%;
height: 8px;
background-color: #e5e7eb;
border-radius: 4px;
overflow: hidden;
}
.progress-bar::before {
content: '';
display: block;
width: var(--progress-width);
height: 100%;
background-color: var(--progress-color);
transition: width 0.3s ease;
}
JavaScript Integration
The real magic happens when you combine CSS custom properties with JavaScript:
// Update progress dynamically
function updateProgress(percentage) {
document.documentElement.style.setProperty(
'--progress-width',
`${percentage}%`
);
}
// Theme switching
function toggleTheme() {
const isDark = document.documentElement.classList.contains('dark');
document.documentElement.classList.toggle('dark', !isDark);
localStorage.setItem('theme', isDark ? 'light' : 'dark');
}
Benefits Over Traditional Approaches
1. Runtime Flexibility
Unlike preprocessor variables, CSS custom properties can be modified at runtime, enabling dynamic themes and responsive designs.
2. Better Performance
No build step required - changes are applied instantly by the browser.
3. Debugging Made Easy
Variables are visible in browser developer tools, making debugging more straightforward.
4. Semantic Naming
Create meaningful variable names that describe purpose rather than values:
:root {
--color-primary: #3b82f6;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-danger: #ef4444;
--spacing-small: 0.5rem;
--spacing-medium: 1rem;
--spacing-large: 2rem;
}
Best Practices
1. Use Meaningful Naming Conventions
/* Good */
--color-brand-primary
--spacing-component-padding
--border-radius-card
/* Avoid */
--blue
--small-space
--rounded
2. Organize by Category
:root {
/* Colors */
--color-primary: #3b82f6;
--color-secondary: #64748b;
/* Typography */
--font-family-sans: 'Inter', sans-serif;
--font-size-base: 1rem;
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
/* Layout */
--container-max-width: 1200px;
--header-height: 4rem;
}
3. Provide Fallbacks
.element {
color: var(--text-color, #333333);
font-size: var(--font-size-medium, 1rem);
}
Real-World Example: Building a Design System
Here’s how I’ve structured the CSS custom properties for this blog:
:root {
/* Brand Colors */
--accent-color: #3b82f6;
--accent-hover: #2563eb;
/* Semantic Colors */
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--bg-tertiary: #f1f5f9;
/* Text Colors */
--text-primary: #0f172a;
--text-secondary: #475569;
--text-tertiary: #94a3b8;
/* Borders & Shadows */
--border-color: #e2e8f0;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
/* Typography */
--font-sans: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}
Conclusion
CSS Custom Properties are no longer a “nice-to-have” feature—they’re essential for modern web development. They provide the foundation for maintainable stylesheets, dynamic theming, and responsive design systems.
Start incorporating them into your projects today, and you’ll wonder how you ever built websites without them!
What’s your experience with CSS custom properties? Share your thoughts and tips in the comments below.