CSS Custom Properties sind weit über einfachen Farbwechsel hinausgegangen. Dieser Leitfaden untersucht die fortgeschrittenen Muster, die CSS Custom Properties zu einem der mächtigsten Features in modernem CSS machen.
Grundlagen der Custom Properties
Custom Properties werden mit dem -- Präfix definiert und mit der var()-Funktion aufgerufen. Sie vererben sich und können in jedem Scope überschrieben werden.
/* CSS Custom Properties — Fundamentals */
/* Define properties on :root for global scope */
:root {
--color-primary: #0066cc;
--color-primary-dark: #0052a3;
--spacing-unit: 8px;
--font-size-base: 1rem;
--border-radius: 4px;
}
/* Use with var() */
.button {
background-color: var(--color-primary);
padding: calc(var(--spacing-unit) * 1.5) calc(var(--spacing-unit) * 3);
border-radius: var(--border-radius);
font-size: var(--font-size-base);
}
/* Override at component scope (not global) */
.button.danger {
--color-primary: #cc0000; /* Only affects this button */
--color-primary-dark: #990000;
}
/* Fallback value (second argument to var) */
.card {
background: var(--card-bg, white);
color: var(--card-text, var(--color-text, #333)); /* nested fallback */
padding: var(--card-padding, var(--spacing-unit, 8px));
}Design-Token-Theming-Systeme
Die leistungsstärkste Verwendung von Custom Properties ist der Aufbau eines vollständigen Design-Token-Systems, das mehrere Themes ohne JavaScript unterstützt.
/* Multi-Theme System with CSS Custom Properties */
/* Light theme (default) */
:root {
--color-bg: #ffffff;
--color-surface: #f8f9fa;
--color-border: #e2e8f0;
--color-text-primary: #1a202c;
--color-text-secondary: #718096;
--color-accent: #3182ce;
--color-accent-hover: #2c5282;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--transition-fast: 150ms ease;
}
/* Dark theme — override only what changes */
[data-theme="dark"] {
--color-bg: #1a202c;
--color-surface: #2d3748;
--color-border: #4a5568;
--color-text-primary: #f7fafc;
--color-text-secondary: #a0aec0;
--color-accent: #63b3ed;
--color-accent-hover: #90cdf4;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
/* High-contrast theme */
[data-theme="high-contrast"] {
--color-bg: #000000;
--color-text-primary: #ffffff;
--color-accent: #ffff00;
--color-border: #ffffff;
}
/* System preference auto-detection */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-bg: #1a202c;
--color-text-primary: #f7fafc;
/* ... more overrides */
}
}
/* Components use semantic tokens — never raw colors */
.card {
background: var(--color-surface);
border: 1px solid var(--color-border);
color: var(--color-text-primary);
box-shadow: var(--shadow-md);
transition: box-shadow var(--transition-fast);
}Komponentenvarianten mit Custom Properties
Custom Properties ermöglichen flexiblere Komponentenvarianten-Systeme als traditionelle Utility-Klassen.
/* Component Variant System */
/* Button component with custom property API */
.btn {
/* Default values (the component's "API") */
--btn-bg: var(--color-accent);
--btn-bg-hover: var(--color-accent-hover);
--btn-color: white;
--btn-border: transparent;
--btn-shadow: var(--shadow-sm);
--btn-size: 1rem;
--btn-padding-y: 0.5em;
--btn-padding-x: 1em;
--btn-radius: var(--border-radius);
background: var(--btn-bg);
color: var(--btn-color);
border: 1px solid var(--btn-border);
box-shadow: var(--btn-shadow);
font-size: var(--btn-size);
padding: var(--btn-padding-y) var(--btn-padding-x);
border-radius: var(--btn-radius);
transition: background var(--transition-fast);
}
.btn:hover {
background: var(--btn-bg-hover);
}
/* Variants — only override what changes */
.btn-danger {
--btn-bg: #e53e3e;
--btn-bg-hover: #c53030;
}
.btn-outline {
--btn-bg: transparent;
--btn-bg-hover: var(--color-accent);
--btn-color: var(--color-accent);
--btn-border: var(--color-accent);
}
.btn-sm {
--btn-size: 0.875rem;
--btn-padding-y: 0.375em;
--btn-padding-x: 0.75em;
}
.btn-lg {
--btn-size: 1.125rem;
--btn-padding-y: 0.75em;
--btn-padding-x: 1.5em;
}
/* Caller overrides — no need for a new variant class */
.special-hero .btn {
--btn-bg: gold;
--btn-color: black;
--btn-radius: 50px;
}JavaScript-Interoperabilität
Custom Properties verbinden CSS und JavaScript nahtlos. Sie können sie von JavaScript aus lesen und schreiben.
// JavaScript <-> CSS Custom Properties
// 1. Read a custom property value
const root = document.documentElement;
const primaryColor = getComputedStyle(root)
.getPropertyValue('--color-primary')
.trim();
console.log(primaryColor); // '#0066cc'
// 2. Set a custom property from JavaScript
root.style.setProperty('--color-primary', '#ff6600');
// 3. Remove a custom property
root.style.removeProperty('--color-primary');
// 4. Theme switcher
function setTheme(theme) {
document.documentElement.dataset.theme = theme;
localStorage.setItem('theme', theme);
}
// 5. Animate with custom properties (requires @property)
// CSS:
// @property --progress {
// syntax: '<number>';
// initial-value: 0;
// inherits: false;
// }
// .progress-bar {
// width: calc(var(--progress) * 1%);
// transition: --progress 1s ease;
// }
// JavaScript:
function animateProgress(el, from, to) {
el.style.setProperty('--progress', from);
requestAnimationFrame(() => {
el.style.setProperty('--progress', to);
});
}
// 6. Reactive properties with ResizeObserver
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
entry.target.style.setProperty('--el-width', `${width}px`);
entry.target.style.setProperty('--el-height', `${height}px`);
}
});
observer.observe(document.querySelector('.responsive-component'));Häufig gestellte Fragen
Sind CSS Custom Properties dasselbe wie SASS-Variablen?
Nein, sie sind grundlegend verschieden. SASS-Variablen werden zur Build-Zeit kompiliert. CSS Custom Properties existieren zur Laufzeit und können mit JavaScript geändert werden.
Können CSS Custom Properties animiert werden?
Ja, mit @property (Houdini). Die @property-Regel ermöglicht fließende Animationen.
Was ist der Fallback-Wert in var()?
Das zweite Argument von var() ist ein Fallback, wenn die Eigenschaft nicht definiert ist.
Funktionieren CSS Custom Properties in allen modernen Browsern?
Ja, volle Browserunterstützung seit 2017.