~/
hackweb.dev
CSS Variables (Custom Properties)
Quiz
⌘K
...
~/
/tutorials
/css/css-variables/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/css/12css-variables
Write
Preview
Diff
# CSS Variables (Custom Properties) CSS variables store reusable values. They make CSS more maintainable and enable dynamic theming. ## Basic Syntax ### Define Variables ```css :root { --primary-color: #3498db; --secondary-color: #2ecc71; --font-size: 16px; --spacing: 1rem; } ``` ### Use Variables ```css .button { background-color: var(--primary-color); font-size: var(--font-size); padding: var(--spacing); } .container { max-width: 1200px; padding: var(--spacing); color: var(--primary-color); } ``` ## Fallback Values Provide default values: ```css .button { background-color: var(--primary-color, #3498db); } .text { font-size: var(--font-size, 16px); } /* Multiple fallbacks */ .element { color: var(--text-color, var(--primary-color, black)); } ``` ## Scope Variables can be scoped: ```css /* Global scope */ :root { --primary-color: #3498db; } /* Component scope */ .card { --card-bg: white; --card-padding: 1rem; background-color: var(--card-bg); padding: var(--card-padding); } .card-dark { --card-bg: #333; --card-padding: 1.5rem; } ``` ## Dynamic Variables Variables can be changed with JavaScript: ```css :root { --primary-color: #3498db; } ``` ```javascript // Change variable document.documentElement.style.setProperty('--primary-color', '#e74c3c'); // Reset variable document.documentElement.style.removeProperty('--primary-color'); ``` ## Complete Example: Theme System ```css /* Light theme (default) */ :root { --bg-primary: #ffffff; --bg-secondary: #f5f5f5; --text-primary: #333333; --text-secondary: #666666; --accent-color: #3498db; --border-color: #dddddd; --shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } /* Dark theme */ [data-theme="dark"] { --bg-primary: #1a1a1a; --bg-secondary: #2d2d2d; --text-primary: #ffffff; --text-secondary: #b0b0b0; --accent-color: #3498db; --border-color: #444444; --shadow: 0 2px 10px rgba(0, 0, 0, 0.3); } /* Apply theme */ body { background-color: var(--bg-primary); color: var(--text-primary); font-family: var(--font-family); } .card { background-color: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 1.5rem; box-shadow: var(--shadow); } .button { background-color: var(--accent-color); color: white; padding: 0.75rem 1.5rem; border: none; border-radius: 5px; cursor: pointer; } ``` ```javascript // Toggle theme function toggleTheme() { const html = document.documentElement; const currentTheme = html.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; html.setAttribute('data-theme', newTheme); } ``` ## Complete Example: Design Tokens ```css /* Spacing scale */ :root { --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 1rem; --space-lg: 1.5rem; --space-xl: 2rem; --space-2xl: 3rem; } /* Typography scale */ :root { --font-size-xs: 0.75rem; --font-size-sm: 0.875rem; --font-size-base: 1rem; --font-size-lg: 1.125rem; --font-size-xl: 1.25rem; --font-size-2xl: 1.5rem; --font-size-3xl: 2rem; } /* Colors */ :root { --color-primary: #3498db; --color-secondary: #2ecc71; --color-success: #27ae60; --color-warning: #f39c12; --color-danger: #e74c3c; } /* Border radius */ :root { --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-full: 9999px; } /* Usage */ .card { padding: var(--space-lg); font-size: var(--font-size-base); border-radius: var(--radius-md); background-color: var(--color-primary); } ``` ## Complete Example: Responsive Typography ```css /* Base typography */ :root { --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); --text-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem); --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); --text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem); --text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem); --text-2xl: clamp(1.5rem, 1.3rem + 1vw, 2rem); } body { font-size: var(--text-base); line-height: 1.6; } h1 { font-size: var(--text-2xl); } h2 { font-size: var(--text-xl); } p { font-size: var(--text-base); } ``` ## Complete Example: Component Library ```css /* Button variants */ :root { --btn-primary-bg: #3498db; --btn-primary-hover: #2980b9; --btn-secondary-bg: #95a5a6; --btn-secondary-hover: #7f8c8d; --btn-success-bg: #27ae60; --btn-success-hover: #219a52; --btn-padding: 0.75rem 1.5rem; --btn-border-radius: 5px; --btn-font-weight: 500; } .button { padding: var(--btn-padding); border-radius: var(--btn-border-radius); font-weight: var(--btn-font-weight); border: none; cursor: pointer; transition: background-color 0.3s, transform 0.2s; } .button-primary { background-color: var(--btn-primary-bg); color: white; } .button-primary:hover { background-color: var(--btn-primary-hover); transform: translateY(-2px); } .button-secondary { background-color: var(--btn-secondary-bg); color: white; } .button-secondary:hover { background-color: var(--btn-secondary-hover); } ``` ## Dynamic Values Change variables based on state: ```css .progress { --progress: 0%; width: var(--progress); height: 20px; background-color: var(--color-primary); transition: width 0.3s ease; } ``` ```javascript // Update progress element.style.setProperty('--progress', '75%'); ``` ## Media Queries with Variables ```css :root { --spacing: 1rem; --font-size: 14px; } @media (min-width: 768px) { :root { --spacing: 1.5rem; --font-size: 16px; } } @media (min-width: 992px) { :root { --spacing: 2rem; --font-size: 18px; } } ``` ## Best Practices 1. **Use :root for global variables** — Available everywhere 2. **Use meaningful names** — `--color-primary` not `--blue` 3. **Provide fallback values** — Always have a default 4. **Group related variables** — Colors, spacing, typography 5. **Use design tokens** — Consistent, reusable values ## Common Mistakes 1. **Not providing fallbacks** — Breaks if variable undefined 2. **Overusing variables** — Not everything needs a variable 3. **Inconsistent naming** — Stick to a convention 4. **Global scope pollution** — Use component scope when appropriate 5. **Not documenting variables** — Hard to understand later
No changes yet
Reset to original
Submit suggestion
cancel