CSS Custom Properties (CSS Variables) have revolutionized how we write and maintain stylesheets. Let's explore advanced patterns and best practices for leveraging this powerful feature.
Understanding Custom Properties
CSS Custom Properties provide:
- Dynamic value updates
- Scoped variables
- Inheritance patterns
- Fallback values
- Runtime modifications
Basic Implementation
Variable Declaration
Define custom properties:
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--spacing-unit: 8px;
--font-scale: 1.2;
}
Usage Patterns
Apply custom properties:
.button {
background-color: var(--primary-color);
padding: calc(var(--spacing-unit) * 2);
margin: var(--spacing-unit);
transition: background-color 0.3s ease;
}
.button:hover {
background-color: var(--secondary-color);
}
Advanced Patterns
Component-Based Variables
Create scoped variables:
.card {
--card-padding: 1rem;
--card-border-radius: 8px;
--card-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: var(--card-padding);
border-radius: var(--card-border-radius);
box-shadow: var(--card-shadow);
}
.card--large {
--card-padding: 2rem;
}
Theming System
Implement comprehensive theming:
:root {
/* Base Colors */
--color-primary-100: hsl(215, 100%, 95%);
--color-primary-500: hsl(215, 100%, 50%);
--color-primary-900: hsl(215, 100%, 20%);
/* Semantic Colors */
--color-text: var(--color-primary-900);
--color-background: var(--color-primary-100);
--color-accent: var(--color-primary-500);
}
[data-theme="dark"] {
--color-text: var(--color-primary-100);
--color-background: var(--color-primary-900);
--color-accent: var(--color-primary-500);
}
Real-World Applications
Responsive Design System
Create a responsive system:
:root {
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
--space-xl: 4rem;
--container-width: 1200px;
--container-padding: var(--space-md);
@media (max-width: 768px) {
--container-padding: var(--space-sm);
}
}
.container {
max-width: var(--container-width);
padding: 0 var(--container-padding);
margin: 0 auto;
}
Typography System
Build a flexible typography system:
:root {
--font-family-base: system-ui, sans-serif;
--font-family-heading: 'Georgia', serif;
--font-size-base: 16px;
--line-height-base: 1.5;
--font-scale-ratio: 1.25;
--font-size-sm: calc(var(--font-size-base) / var(--font-scale-ratio));
--font-size-lg: calc(var(--font-size-base) * var(--font-scale-ratio));
--font-size-xl: calc(var(--font-size-lg) * var(--font-scale-ratio));
}
body {
font-family: var(--font-family-base);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
}
h1, h2, h3 {
font-family: var(--font-family-heading);
}
Best Practices
Organization
Structure custom properties:
:root {
/* Colors */
--color-brand-primary: #007bff;
--color-brand-secondary: #6c757d;
/* Spacing */
--spacing-unit: 8px;
--spacing-xs: calc(var(--spacing-unit) * 0.5);
--spacing-sm: var(--spacing-unit);
--spacing-md: calc(var(--spacing-unit) * 2);
--spacing-lg: calc(var(--spacing-unit) * 3);
/* Typography */
--font-size-base: 16px;
--font-family-base: system-ui, sans-serif;
/* Layout */
--container-max-width: 1200px;
--sidebar-width: 250px;
}
Fallback Values
Implement robust fallbacks:
.element {
/* Fallback for older browsers */
background-color: #007bff;
background-color: var(--primary-color, #007bff);
/* Multiple fallbacks */
margin: var(--custom-margin, var(--default-margin, 1rem));
}
Advanced Use Cases
Dynamic Calculations
Use complex calculations:
:root {
--golden-ratio: 1.618;
--base-size: 16px;
--h1-size: calc(var(--base-size) * var(--golden-ratio) * var(--golden-ratio));
--h2-size: calc(var(--base-size) * var(--golden-ratio));
}
.fluid-type {
--min-width: 320;
--max-width: 1200;
--min-size: 16;
--max-size: 24;
font-size: calc(
var(--min-size) * 1px +
(var(--max-size) - var(--min-size)) *
(100vw - var(--min-width) * 1px) /
(var(--max-width) - var(--min-width))
);
}
Component API
Create component APIs:
.button {
--button-background: var(--color-primary);
--button-color: white;
--button-padding: 0.5em 1em;
--button-border-radius: 4px;
background: var(--button-background);
color: var(--button-color);
padding: var(--button-padding);
border-radius: var(--button-border-radius);
}
.button--large {
--button-padding: 1em 2em;
}
Performance Considerations
Optimization
Optimize variable usage:
/* Good - Computed once */
.element {
--computed-value: calc(var(--base) * 2);
width: var(--computed-value);
height: var(--computed-value);
}
/* Bad - Computed twice */
.element {
width: calc(var(--base) * 2);
height: calc(var(--base) * 2);
}
Scoping
Properly scope variables:
.component {
--private-value: 42;
.child {
/* Use scoped variable */
margin: calc(var(--private-value) * 1px);
}
}
Conclusion
CSS Custom Properties provide powerful capabilities for modern stylesheets. Key takeaways:
- Use semantic naming
- Implement proper scoping
- Create robust fallbacks
- Optimize calculations
- Build component APIs
Remember to:
- Structure variables logically
- Consider browser support
- Use appropriate scoping
- Implement fallbacks
- Monitor performance
Custom Properties represent a fundamental tool for creating maintainable and flexible CSS architectures.