Was sind CSS-Variablen?
CSS-Variablen, korrekt eigentlich custom properties genannt, sind Werte, die man einmal definiert und dann überall referenziert. Sie sehen aus wie gewöhnliche Properties, beginnen jedoch mit -- und werden mit der var()-Funktion ausgelesen.
/* tokens.css */
:root {
--color-brand: #2563eb;
--radius: 0.5rem;
--space-4: 1rem;
}
.button {
background: var(--color-brand);
border-radius: var(--radius);
padding: var(--space-4) calc(var(--space-4) * 1.5);
}
Der entscheidende Unterschied zu Variablen in einem Preprocessor besteht darin, dass custom properties Teil des Browser-Cascades sind. Sie werden vererbt, können in ihrem Scope begrenzt werden und können zur Laufzeit geändert werden. Das macht sie zur idealen Lösung für Theming und Design Tokens.
Deklarieren und Verwenden
Deklarieren Sie eine Custom Property mit einem Namen, der mit zwei Bindestrichen beginnt, und einem beliebigen gültigen Wert.
/* declare.css */
:root {
--gap: 1.5rem;
--shadow: 0 1px 2px rgb(0 0 0 / 0.08);
--font-sans: "Inter", system-ui, sans-serif;
}
.card {
gap: var(--gap);
box-shadow: var(--shadow);
font-family: var(--font-sans);
}
Werte können fast alles sein: Farben, Längen, Schatten, Font-Stacks, Gradienten oder sogar Fragmente eines Wertes. Da sie ersetzt werden, bevor die Property geparst wird, können sie mit calc() kombiniert werden.
Die Kaskade und Vererbung
Custom Properties folgen den normalen CSS-Regeln. Eine Deklaration an einem Element wird an dessen Nachfahren vererbt, wobei die am nächsten liegende Deklaration Vorrang hat.
/* scope.css */
:root {
--accent: #2563eb;
}
.sidebar {
--accent: #f97316;
}
.sidebar a {
color: var(--accent); /* orange inside the sidebar */
}
Genau das macht das Scoping so leistungsfähig: Sie können das Theme einer Komponente oder eines Abschnitts ändern, ohne die globalen Tokens anzupassen. Aus diesem Grund sind Tokens, die auf :root definiert werden, überall verfügbar.
Fallbacks
var() akzeptiert ein Fallback als zweites Argument, das verwendet wird, wenn die Eigenschaft fehlt oder ungültig ist.
/* fallback.css */
.button {
color: var(--button-color, #ffffff);
background: var(--button-bg, var(--color-brand, #2563eb));
}
Fallbacks sind nützlich für wiederverwendbare Komponenten, die auch dann funktionieren sollen, wenn keine Tokens definiert sind; zudem können sie verschachtelt werden. Setze sie jedoch sparsam ein: Wenn ein Token immer existieren sollte, definiere es klar, anstatt das Problem zu verschleiern.
Theming
Theming ist der Paradefall für diesen Ansatz. Tauschen Sie einen Satz von Variablen aus, und ein gesamter Teilbaum wird aktualisiert.
/* theme.css */
:root {
--bg: #ffffff;
--surface: #f8fafc;
--text: #0f172a;
--border: #e2e8f0;
}
[data-theme="dark"] {
--bg: #0b0d0c;
--surface: #14161a;
--text: #e5e7eb;
--border: #26292e;
}
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--surface);
border: 1px solid var(--border);
}
Aktivieren Sie ein data-theme Attribut am Root-Element, und die gesamte Seite passt ihr Theme sofort an, ohne dass Regeln dupliziert werden müssen. Sie können ein Theme auch auf eine Komponente beschränken, sodass beispielsweise eine dunkle Card auf einer hellen Seite platziert werden kann.
Dynamische Werte mit JavaScript
Da Custom Properties im DOM existieren, können Sie diese mit JavaScript auslesen und beschreiben.
// progress.js
const bar = document.querySelector(".progress");
function setProgress(percent) {
bar.style.setProperty("--progress", `${percent}%`);
}
setProgress(72);
/* progress.css */
.progress__fill {
width: var(--progress, 0%);
}
Auf diese Weise werden üblicherweise Fortschrittsbalken, Drag-Interaktionen, Cursor-Following-Effekte und Theme-Toggles implementiert. Der Wert verbleibt in CSS und JavaScript aktualisiert lediglich eine Zahl.
Typisierte Properties mit @property
Standardmäßig sind Custom Properties untypisierte Strings, weshalb der Browser sie nicht interpolieren kann. Die @property At-Rule registriert einen Typ, einen Initialwert und ein Vererbungsvariablen-Verhalten.
/* property.css */
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--angle), #2563eb, transparent);
animation: rotate 1s linear infinite;
}
@keyframes rotate {
to { --angle: 360deg; }
}
Mit einem registrierten Typ wird die Property animierbar und der Browser validiert den Wert, was eine ganze Klasse von Bugs verhindert.
Best Practices
- Definiere globale Tokens in
:rootund verwende sie konsistent im gesamten Projekt. - Benenne Tokens nach ihrem Verwendungszweck (
--color-text) und nicht nach ihrem Aussehen (--gray-900). - Überschreibe Variablen für Themes und Komponenten-Varianten, anstatt Regeln zu duplizieren.
- Biete Fallbacks für wiederverwendbare Komponenten an, die möglicherweise ohne Tokens ausgeführt werden.
- Aktualisiere Variablen über JavaScript, anstatt überall Inline-Styles zu schreiben.
- Registriere animierbare Eigenschaften mit
@property. - Halte den Token-Satz klein und konsistent.
Häufige Fehler
- Die Erwartung, dass sich Custom Properties zur Build-Zeit wie Sass-Variablen verhalten.
- Die Verwendung vager Namen, die die Wartung des Token-Sets erschweren.
- Die Definition jedes einzelnen Wertes als Variable, wodurch die Lesbarkeit leidet.
- Zu vergessen, dass Werte untypisiert sind, sofern sie nicht mit
@propertyregistriert wurden. - Das globale Überschreiben von Tokens, wenn eigentlich nur ein Teilbaum geändert werden sollte.
- Das Speichern von Secrets oder Benutzerdaten in CSS-Variablen, die im DOM sichtbar sind.
Wie geht es weiter?
Custom Properties sind das Bindeglied eines wartbaren Stylesheets. Wende sie im Layout mit Responsive Design an, animiere typisierte Properties mit Animations & Transitions und verstehe die dahinterliegende Kaskade im CSS guide. Für Build-Time-Variablen, die diese ergänzen, schau dir Sass an.