CSS-Variablen: Die Engine moderner Designsysteme
SASS-Variablen sterben zur Kompilierzeit. CSS-Variablen leben im Browser. Ein technischer Leitfaden für semantisches Layering, dynamisches Theming und Komponentenisolation.
Ein Jahrzehnt lang war SASS König. Wir haben „€brand-color: #ff0000;“ definiert. Wir haben es zusammengestellt. Aber SASS-Variablen haben einen schwerwiegenden Fehler: Sie sterben zur Kompilierungszeit. Sobald das CSS den Browser erreicht, ist die Variable verschwunden. Es ist nur ein statischer Hex-Code. Sie können es nicht mit JavaScript ändern. Sie können es nicht auf einen bestimmten DOM-Knoten beschränken.
Geben Sie Benutzerdefinierte CSS-Eigenschaften (Variablen) ein.
--brand-color: #ff0000;.
Dabei handelt es sich nicht nur um „Variablen“. Sie sind Eigenschaften des DOM. Sie kaskadieren. Sie leben.
Bei Maison Code Paris verwenden wir sie als Grundschicht jedes von uns erstellten Designsystems.
Warum Maison Code darüber spricht
Bei Maison Code Paris fungieren wir als das architektonische Gewissen unserer Kunden. Wir übernehmen oft „moderne“ Stacks, die ohne grundlegendes Verständnis für Skalierung gebaut wurden.
Wir diskutieren dieses Thema, weil es einen kritischen Wendepunkt in der technischen Reife darstellt. Die korrekte Implementierung unterscheidet ein fragiles MVP von einer widerstandsfähigen Plattform auf Unternehmensniveau.
1. Die semantische Layering-Strategie
Anfänger ordnen Variablen direkt Farben zu.
--blue: #0000ff;
Experten ordnen Variablen Intent zu.
Wir verwenden eine 3-Schichten-Architektur:
Ebene 1: Grundelemente (Die Palette)
Dies ist Ihr Rohfarbkasten. Es hat keine Bedeutung, nur Werte. „css :root { —palette-blue-100: #ebf8ff; —palette-blue-500: #4299e1; —palette-blue-900: #2a4365; —palette-neutral-900: #1a202c; —palette-white: #ffffff; } „
Schicht 2: Semantik (Das Token)
Dadurch wird die Palette einem bestimmten Zweck zugeordnet. „css :root { —bg-primary: var(—palette-white); —bg-secondary: var(—palette-blue-100); —text-body: var(—palette-neutral-900); —action-primary: var(—palette-blue-500); —action-primary-hover: var(—palette-blue-900); } „
Schicht 3: Komponente (die Nutzung)
Auschecken einer Komponente. „css .btn-primär { Hintergrundfarbe: var(—action-primary); Farbe: var(—bg-primary); } „
Warum? Wenn die Marke entscheidet „Primäre Aktion ist jetzt Lila“, ändern Sie eine Zeile in Ebene 2. Sie grepen/seden nicht die gesamte Codebasis.
2. Dynamisches Theming (Dunkler Modus)
Da CSS-Variablen zur Laufzeit aufgelöst werden, ist die Implementierung des Dark Mode trivial. Sie definieren Layer 2 einfach innerhalb eines Datenattributs neu.
„css [data-theme=“dark”] { —bg-primary: var(—palette-neutral-900); —bg-secondary: var(—palette-black); —text-body: var(—palette-white); } „
Wenn Sie das Attribut auf „“ umschalten, wird die gesamte Site sofort neu gezeichnet (mit 60 fps), da der Browser nur die Zeiger vertauscht. Kein Neuladen des Stylesheets erforderlich.
3. Scoping und Isolierung
Variablen gehorchen der Kaskade. Dies ermöglicht ein leistungsstarkes kontextuelles Styling. Stellen Sie sich einen „dunklen Abschnitt“ in der Mitte einer hellen Seite vor.
„css .section-inverted { —text-body: var(—palette-white); —bg-primary: var(—palette-neutral-900); } „
Jede Komponente (Karte, Schaltfläche, Text), die in „.section-inverted“ platziert wird, übernimmt automatisch die „Dunkel“-Werte, auch wenn der Rest der Seite hell ist. Der Komponentencode ändert sich nicht. Es verbraucht lediglich die Variable von ihrem nächsten übergeordneten Element.
4. JavaScript-Interaktion: Mausverfolgung
Sie können Variablen von JS lesen/schreiben. Dies ermöglicht leistungsstarke UI-Effekte ohne React-Re-Renderings.
Der Spotlight-Effekt „Cursor folgen“:
„Javascript
document.addEventListener(‘mousemove’, (e) => {
const x = e.clientX;
const y = e.clientY;
document.body.style.setProperty(‘—mouse-x’, €{x}px);
document.body.style.setProperty(‘—mouse-y’, €{y}px);
});
„
„css .spotlight { Hintergrund: radial-gradient( Kreis bei var(—mouse-x) var(—mouse-y), rgba(255, 255, 255, 0,2), transparent 150px ); } „ Dies läuft (meistens) vollständig im CSS-Compositor-Thread.
5. Integration mit Tailwind CSS
Wir lieben Rückenwind. Aber die Hartcodierung von Hex-Werten in „tailwind.config.js“ ist ein Anti-Pattern. Verknüpfen Sie Tailwind mit Ihrer semantischen Ebene.
„Javascript // tailwind.config.js module.exports = { Thema: { Farben: { // Verwenden Sie die CSS-Variable, nicht das Hex Primary: ‘var(—action-primary)’, Hintergrund: ‘var(—bg-primary)’, text: ‘var(—text-body)’, } } } „ Jetzt generiert „bg-primary“ „.bg-primary {background-color: var(—action-primary)}“. Sie erhalten den Utility-Workflow, behalten aber die Laufzeitflexibilität.
6. Leistungsfallen
- Scope Root Changes: Das Ändern einer Variable auf „:root“ löst eine Stilneuberechnung für den gesamten DOM-Baum aus. Es ist schnell, aber es ist riskant, es bei einem „Scroll“-Event durchzuführen. Bevorzugen Sie Bereichsänderungen für bestimmte Container.
- calc()-Komplexität: „width: calc(var(—a) * var(—b) + 10px)“ zwingt den Browser, in jedem Frame Berechnungen durchzuführen, wenn sich die Variablen ändern. Sparsam verwenden.
7. Die Leistung von „calc()“ im Vergleich zu Precomputed
Browser Math ist schnell, aber nicht kostenlos. „width: calc(var(—a) * var(—b))“ wird bei jeder Layout-Neuberechnung ausgeführt. Wenn Sie 10.000 Knoten haben, die dies tun, sinkt die Geschwindigkeit von 60 fps auf 30 fps. Optimierung: Wenn der Wert für eine Komponente statisch ist, berechnen Sie ihn nach Möglichkeit in JS oder SASS vor. Verwenden Sie CSS-Variablen für Werte, die sich zur Laufzeit ändern (Design, Dimensionen, Benutzerkonfiguration). Verwenden Sie sie nicht nur, um das Eintippen von Zahlen zu vermeiden.
8. Verwenden von Variablen für Animationszustände
Anstatt „transformieren“ zu animieren, animieren Sie eine Variable. „css .card { transform: TranslateY(var(—y, 0)) Scale(var(—s, 1)); Übergang: —y 0,2s, —s 0,2s; } .card:hover { —y: -10px; —s: 1,05; } „ Dies ist sauberer als die Neudefinition der gesamten „Transform“-Zeichenfolge. Es ermöglicht auch unabhängige Animationen (z. B. JS aktualisiert „—y“, während CSS „—s“ aktualisiert). Es reduziert den „CSS String Parsing“-Overhead für den Browser.
9. Fallback-Strategien
Stellen Sie für kritische Bibliotheken immer einen Fallback bereit.
color: var(--text-body, black);
Wenn der Benutzer Ihre Komponente lädt, aber vergisst, das Design System-CSS einzubinden, wird sie trotzdem schwarz und nicht unsichtbar gerendert.
9. Containerabfragen: Kontextvariablen
Medienabfragen („@media (min-width: 768px)“) fragen den Bildschirm ab. Containerabfragen („@container (min-width: 300px)“) fragen das Parent ab. Dies verändert unsere Denkweise über Variablen. Eine Karte kann sagen: „Wenn mein Container klein ist, „—padding: 1rem“. Wenn mein Container groß ist, „—padding: 2rem“. Dadurch werden Komponenten wirklich tragbar. Sie können die „Produktkarte“ in eine Seitenleiste (klein) oder ein Hauptraster (groß) einfügen und sie passt ihre eigene interne Logik ohne externe Überschreibungen an.
10. Typisiertes CSS-Objektmodell (Houdini)
Was wäre, wenn Sie Ihre CSS-Variablen einer Typprüfung unterziehen könnten?
CSS.registerProperty({ name: '--brand-color', syntax: '<color>', initialValue: 'black', inherits: true })
Das ist Houdini.
Es teilt dem Browser mit: „—brand-color IST EINE FARBE“.
Wenn Sie versuchen, es auf „10px“ zu setzen, wird es vom Browser ignoriert.
Noch wichtiger ist, dass der Browser es jetzt richtig animieren kann, da er weiß, dass es sich um eine Farbe (Interpolation von RGB-Werten) und nicht nur um eine Zeichenfolge handelt.
12. Houdini: The Deep Dive
Bei Houdini geht es nicht nur um Typen. Es geht um Leistung. Wenn Sie eine Standardvariable animieren, führt der Browser in jedem Frame eine Zeichenfolgenmanipulation durch. „10px“ -> „11px“ -> „12px“`. Mit „CSS.registerProperty“ erfolgt eine schnelle Float-Interpolation. „10,0 -> 11,0 -> 12,0“. Dadurch wird die Arbeit vom Haupt-Thread in den Compositor-Thread verschoben. Die Animation bleibt flüssig, auch wenn React den Hauptthread durch eine schwere Hydratationsaufgabe blockiert.
13. Die @property-Regel (Zukunftssicherheit)
Wir haben Houdini erwähnt. Es ist jetzt in Chrome stabil.
„css
@property —gradient-angle {
Syntax: 'keyframe rotieren { zu { --gradient-angle: 360deg; } }
„Hintergrund: conic-gradient(from var(—gradient-angle), red, blue);“.
Das war vorher unmöglich.
Sie mussten JS/Canvas verwenden. Jetzt ist es natives CSS.
Dadurch werden komplexe Animationen mit 60 Bildern pro Sekunde im Compositor freigeschaltet.
14. Warum Maison Code?
Bei Maison Code liefern wir Designsysteme, nicht nur Websites. Wir definieren Ihre Markentokens in JSON (Figma). Wir exportieren sie automatisch in CSS-Variablen. Wir stellen sicher, dass Ihr Dark Mode kein nachträglicher Einfall ist, sondern ein erstklassiger Bürger. Wir erstellen Architekturen, die es Ihnen ermöglichen, Ihre gesamte Website in 5 Minuten umzubenennen, indem Sie ein paar Hex-Codes ändern. Wir legen ebenso großen Wert auf Wartbarkeit wie auf Ästhetik.
14. Checkliste für CSS-Variablen
Bevor Sie Ihr Design System versenden:
- Namespace: Setzen Sie ein Präfix? „—ds-color-primary“ vs. „—color-primary“.
- Fallback: Haben Sie einen Fallback-Wert?
var(--color, #000). - Drucken: Funktionieren Ihre Variablen im Druckmodus („@media print“)?
- Kontrast: Überprüfen Sie die Zugänglichkeit Ihrer Dark Mode-Varianten.
- Leistung: Vermeiden Sie „calc()“ in Scroll-Handlern.
- Vererbung: Verwenden Sie „inherits: true“ für @property?
- JS-Synchronisierung: Liest Ihr JS die richtige Variable?
- Linting: Verwenden Sie „stylelint“, um die Verwendung von Variablen über Hex zu erzwingen.
- Dokumentation: Gibt es ein Storybook, das alle Token zeigt?
- Versionierung: Wie gehen Sie mit wichtigen Änderungen in Token um?
15. Fazit
CSS-Variablen sind das wichtigste Werkzeug zur Skalierung der Front-End-Architektur. Sie schließen die Lücke zwischen „Design“ (Figma Tokens) und „Code“ (CSS). Wenn Sie sie nicht verwenden, bauen Sie kein System auf. Du malst nur Seiten. Stoppen Sie die Hardcodierung von Hexadezimalwerten. Fangen Sie an, in Tokens zu denken.
**[Beauftragen Sie unsere Architekten](/contact)**.