Uses var(--demo-primary)
1. Defining & Using Variables
CSS custom properties start with -- and are accessed with var(). Define global variables in :root.
Uses var(--demo-secondary)
Uses var(--demo-success)
/* Define global variables in :root */
:root {
--primary: #6366f1;
--secondary: #8b5cf6;
--success: #10b981;
--spacing: 1rem;
--radius: 0.5rem;
}
/* Use variables with var() */
.button {
background: var(--primary);
padding: var(--spacing);
border-radius: var(--radius);
}2. Fallback Values
Provide fallback values for undefined variables. You can even chain fallbacks.
var(--undefined, #64748b) falls back to gray.
/* Single fallback */
.element {
color: var(--text-color, #1e293b);
}
/* Chained fallback (variable to variable) */
.element {
background: var(--brand-color, var(--primary, blue));
}
/* Fallback for spacing */
.card {
padding: var(--card-padding, var(--spacing, 1rem));
}3. Using calc() with Variables
Combine variables with calc() for dynamic spacing, sizing, and more.
Padding multiplied with calc().
:root {
--spacing: 1rem;
}
.box--sm { padding: calc(var(--spacing) * 0.5); } /* 0.5rem */
.box--md { padding: calc(var(--spacing) * 1); } /* 1rem */
.box--lg { padding: calc(var(--spacing) * 1.5); } /* 1.5rem */
.box--xl { padding: calc(var(--spacing) * 2); } /* 2rem */
/* Create a spacing scale */
:root {
--space-unit: 0.25rem;
--space-1: calc(var(--space-unit) * 1); /* 0.25rem */
--space-2: calc(var(--space-unit) * 2); /* 0.5rem */
--space-4: calc(var(--space-unit) * 4); /* 1rem */
--space-8: calc(var(--space-unit) * 8); /* 2rem */
}4. Scoped Variables
Variables cascade down the DOM. Define them on specific elements to create variants.
Uses default card variables.
Overrides with --dark class.
Overrides with --brand class.
/* Base component with scoped variables */
.card {
--card-bg: white;
--card-color: #1e293b;
--card-border: #e2e8f0;
background: var(--card-bg);
color: var(--card-color);
border: 2px solid var(--card-border);
}
/* Dark variant - just override the variables */
.card--dark {
--card-bg: #1e293b;
--card-color: #f8fafc;
--card-border: #334155;
}
/* Brand variant */
.card--brand {
--card-bg: #eef2ff;
--card-color: #4338ca;
--card-border: #c7d2fe;
}5. Component Variants Pattern
Create component variants by overriding internal variables instead of rewriting styles.
All buttons share the same base styles. Variants just change variables.
/* Base button with internal variables */
.btn {
--btn-bg: var(--primary);
--btn-color: white;
--btn-hover-bg: #4f46e5;
background: var(--btn-bg);
color: var(--btn-color);
/* ...other styles... */
}
.btn:hover {
background: var(--btn-hover-bg);
}
/* Variants just override the variables */
.btn--success {
--btn-bg: var(--success);
--btn-hover-bg: #059669;
}
.btn--outline {
--btn-bg: transparent;
--btn-color: var(--primary);
--btn-hover-bg: #eef2ff;
border: 2px solid var(--primary);
}6. Theme Switching
Override variables with data-theme attribute for dark mode and other themes.
Theme Preview
Click "Toggle Dark" to switch themes using data-theme.
/* Light theme (default) */
.app {
--bg: #ffffff;
--surface: #f8fafc;
--text: #1e293b;
--muted: #64748b;
--border: #e2e8f0;
--accent: #6366f1;
}
/* Dark theme override */
.app[data-theme="dark"] {
--bg: #0f172a;
--surface: #1e293b;
--text: #f8fafc;
--muted: #94a3b8;
--border: #334155;
--accent: #818cf8;
}
/* Components use the variables */
.card {
background: var(--surface);
color: var(--text);
border: 1px solid var(--border);
}
/* JS to toggle */
const toggle = () => {
const app = document.querySelector('.app');
const isDark = app.dataset.theme === 'dark';
app.dataset.theme = isDark ? '' : 'dark';
};7. Design Token: Spacing Scale
Build a consistent spacing scale using a single base unit multiplied with calc().
Each step is a multiple of --space-unit: 0.25rem.
/* Spacing scale based on 0.25rem unit */
:root {
--space-unit: 0.25rem;
--space-1: calc(var(--space-unit) * 1); /* 0.25rem */
--space-2: calc(var(--space-unit) * 2); /* 0.5rem */
--space-3: calc(var(--space-unit) * 3); /* 0.75rem */
--space-4: calc(var(--space-unit) * 4); /* 1rem */
--space-6: calc(var(--space-unit) * 6); /* 1.5rem */
--space-8: calc(var(--space-unit) * 8); /* 2rem */
--space-12: calc(var(--space-unit) * 12); /* 3rem */
--space-16: calc(var(--space-unit) * 16); /* 4rem */
}
/* Usage */
.card {
padding: var(--space-4);
margin-bottom: var(--space-6);
gap: var(--space-2);
}8. Design Token: Color Palette
Define a color palette with shade variations for consistent theming.
Define semantic color tokens for primary, success, warning, and accent colors.
/* Brand color palette */
:root {
--rose: #f43f5e;
--orange: #f97316;
--amber: #f59e0b;
--emerald: #10b981;
--teal: #14b8a6;
--cyan: #06b6d4;
--sky: #0ea5e9;
--indigo: #6366f1;
--violet: #8b5cf6;
--fuchsia: #d946ef;
/* Semantic color tokens */
--color-primary: var(--indigo);
--color-success: var(--emerald);
--color-warning: var(--amber);
--color-danger: var(--rose);
}