Eine Möglichkeit, mit Custom Properties zu arbeiten, besteht darin, sie als Design-Tokens zu betrachten. Farben, Abstände, Schriftarten und dergleichen. Sie legen sie am Stamm der Seite fest und verwenden sie in Ihrem gesamten CSS. Sehr nützlich und der klassische Anwendungsfall nicht nur für Custom Properties, sondern auch für Präprozessor-Variablen seit einer Million Jahren.
Eine weitere Möglichkeit, mit Custom Properties zu arbeiten, die zusätzlich zum Ansatz mit Design-Tokens erfolgen kann, besteht darin, noch viel mehr zu tun und sie für jede wichtige einzigartige Stilwahl an einem bestimmten Element zu verwenden.
Stellen Sie sich vor, Sie haben eine Karte wie diese (zur Veranschaulichung vereinfacht, natürlich)
.card {
background: hsl(200deg 15% 73%);
border: 4px solid rgb(255 255 255 / 0.5);
padding: 2rem;
border-radius: 8px;
}
.card > h2 {
margin: 0 0 1rem 0;
border-bottom: 3px solid rgba(0 0 0 / 0.2);
}
Gut.
Aber wenn Sie dann zwangsläufig Variationen der Karte erstellen, sind Sie auf sich allein gestellt, um diese Regelwerke zu überschreiben. Ein CSS Custom Property-Ansatz kann wie folgt aussehen:
.card {
--card-background: hsl(200deg 15% 73%);
--card-border: 4px solid rgb(255 255 255 / 0.5);
--card-padding: 2rem;
--card-border-radius: 8px;
--card-title-margin: 0 0 1rem 0;
--card-title-border: 3px solid rgba(0 0 0 / 0.2);
background: var(--card-background);
border: var(--card-border);
padding: var(--card-padding);
border-radius: var(--card-border-radius);
}
.card > h2 {
margin: var(--card-title-margin);
border-bottom: var(--card-title-border);
}
Für den Moment etwas wortreicher, aber schauen Sie, was passiert, wenn wir eine Variation erstellen wollen
.card-variation {
--card-background: purple;
--card-padding-block: 2.5rem;
--card-title-margin: 0 0 2rem 0;
}
Hier sind drei klare Vorteile auf Anhieb
- Ich ändere nur Werte, die ich eindeutig zum Ändern eingerichtet habe. Mein Hauptkartenprototyp behält die Integrität, die ich wünsche.
- Ich kann Kinder der Variation gestalten, ohne diese Selektoren neu schreiben zu müssen.
- Ich kann jetzt Stil-Overrides aus dem
style-Attribut in HTML für schnelle, einmalige Variationen übergeben.
Weniger wortreich mit Fallbacks
Anstatt die Custom Properties oben zu deklarieren und sie direkt darunter zu verwenden, kann ich beides gleichzeitig tun, so:
.card {
background: var(--card-background, hsl(200deg 15% 73%));
border: var(--card-border, 4px solid rgb(255 255 255 / 0.5));
padding: var(--card-padding, 2rem);
border-radius: var(--card-border-radius, 8px);
}
.card > h2 {
margin: var(--card-title-margin, 0 0 1rem 0);
border-bottom: var(--card-title-border, 3px solid rgba(0 0 0 / 0.2));
}
Wenn nun etwas wie --card-background gesetzt wird, überschreibt es den Fallback-Wert hier. Das gefällt mir nicht ganz, weil es bedeutet, dass Elemente, die sich *oberhalb* von .card befinden, es überschreiben können. Das ist vielleicht das, was Sie wollen, aber es ist nicht genau dasselbe, als wenn Sie die Werte auf der Ebene von .card deklarieren würden. Hierzu habe ich keine starken Meinungen.
Noch mehr aufbrechen
Ein Beispiel hierfür ist, dass Sie möglicherweise den Abstand individuell steuern möchten.
.card {
--card-padding-block: 2rem;
--card-padding-inline: 2rem;
--card-padding: var(--card-padding-block) var(--card-padding-inline);
padding: var(--card-padding);
}
Nun kann eine Variation nur einen Teil des Abstands steuern, wenn ich möchte
.card-variation {
--card-padding-inline: 3rem;
}
Sie müssen jedoch auf den großen Haken aufpassen. Das bedeutet, wenn Sie all diese am Stamm deklarieren, wird dies nicht funktionieren, da diese verschachtelten Eigenschaften bereits aufgelöst wurden. Aber solange es zuerst auf .card deklariert ist, sind Sie hier auf der sicheren Seite.
Zu weit?
Sagen wir, Sie wollten ultimative Kontrolle über jeden Teil eines Wertes. Zum Beispiel
html {
--color-1-h: 200deg;
--color-1-s: 15%;
--color-1-l: 73%;
--color-1-hsl: var(--color-1-h) var(--color-1-s) var(--color-1-l);
--color-1: hsl(var(--color-1-hsl));
}
Das ist *irgendwie* nett, aber wahrscheinlich zu weit. Farben werden fast sicher am Stamm deklariert und unverändert gelassen, daher wird der große Haken das Überschreiben der Low-Level-Kind-Eigenschaften unmöglich machen. Außerdem, wenn Sie eine --color-1 haben, haben Sie wahrscheinlich auch eine 2-9 (oder mehr), was alles gut und schön ist, weil ein Farbsystem viel delikateres Design-Magie hat als einfache mathematische Manipulationen von Farbteilen.
Lieferbare Design-Systeme?
Es besteht kein Zweifel, dass Tailwind eine große Popularität genießt. Es verwendet einen atomaren Ansatz, bei dem eine Reihe von HTML-Klassen jeweils eine Eigenschaft steuert. Ich würde argumentieren, dass ein Teil dieser Popularität dadurch angetrieben wird, dass, wenn Sie aus diesen vorkonfigurierten Klassen wählen, das Design ziemlich gut aussieht. Sie können nicht vom Kurs abkommen. Sie wählen aus einer begrenzten Auswahl von Werten, die so gestaltet wurden, dass sie gut aussehen.
Ich würde nicht so weit gehen zu sagen, dass ein stark auf Custom Properties basierender Styling-Ansatz genau dasselbe ist. Sie müssen zum Beispiel immer noch eine Klassenabstraktion in Betracht ziehen, anstatt Stile direkt auf das HTML-Element anzuwenden. Aber es könnte einige der gleichen Einschränkungen/Grenzen genießen, die Tailwind und andere atomare Klassenansätze wünschenswert machen. Wenn Sie nur aus einem vordefinierten Satz von --spacing-x-Werten, --color-x-Werten und --font-x-Werten auswählen können, erzielen Sie möglicherweise ein kohärenteres Design, als Sie es sonst hätten.
Persönlich habe ich festgestellt, dass die Hinwendung zu einem Designsystem, das stärker auf Custom Properties basiert, sich gut anfühlt – wenn auch nur, um Variationen und Overrides sinnvoller zu verwalten.
Was ist mit Drittanbieter-Designsystemen, die liefern, was sie liefern, als… nichts weiter als eine große Menge an Custom Properties, die Sie nach Belieben verwenden können?

Drittanbieter-Lieferungen müssen nicht einmal das ganze Kitchen Sink sein wie dieses. Adam Argyle's transition.style stellt zum Beispiel ein „Hackpack“ zur Verfügung, das nichts weiter als Custom Properties von Übergangsanimation-Helfern sind.
Verständlichkeitskosten
Ein Einwand, den ich gegen diesen umfassenderen Ansatz bei Custom Properties gehört habe, ist die Verständlichkeit für Neulinge. Wenn *Sie* das System geschrieben haben, ergibt es für Sie wahrscheinlich perfekten Sinn. Aber es ist eine zusätzliche Abstraktion auf CSS. CSS-Kenntnisse werden von allen geteilt, bespoke Systemkenntnisse werden nur von den Leuten geteilt, die aktiv daran arbeiten.
Frisch in ein System zu kommen, das stark Custom Properties verwendet, wird eine verdammt steile Lernkurve haben.
Ich habe bemerkt, dass YouTube diesen Ansatz mit seinen benutzerdefinierten Eigenschaften verfolgt. Das ist ziemlich nett, ehrlich gesagt.
Ich verfolge diesen Ansatz speziell mit BEM-Modifikatoren. Ich hatte es wirklich satt, dass ich tun musste
Oder sogar das Kind in den Modifikator verschachteln. In beiden Fällen zeigt man in keinem einzigen Regelwerk, was der Modifikator tatsächlich tut, man muss alle potenziell betroffenen Kinder heraussuchen. Die Verwendung von benutzerdefinierten Eigenschaften löst das so schön
Ich denke, das größte Problem mit Ihrem zweiten Beispiel – wenn Sie jede Eigenschaft in Ihrer CSS-Regel (.card) konfigurierbar machen – zu diesem Zeitpunkt können Sie genauso gut atomare Klassen entweder im HTML verwenden oder eine neue .card-variant und Tailwinds @apply hinzufügen.
Als allgemeine Faustregel denke ich, dass der Ansatz des „konfigurierbaren Komponenten“ sinnvoll ist, wenn es um kleine Varianten einer Komponente geht. Andernfalls führt dies zu schlechtem Design – wo eine neue Komponente die bessere und wartbarere Antwort gewesen wäre.
Es ist im Grunde so, als ob man beim Design von Code auf die „Domäne“ dieser speziellen visuellen Variante von etwas schauen muss.
Manchmal ist die Domäne dieselbe, wie H2-Überschriften, die basierend auf dem Website-Abschnitt unterschiedliche Farben haben.
Aber manchmal ändert man den Stil einer Karte, um sie zum Beispiel in eine „Info-Box“ zu verwandeln, und man hat die Domäne geändert. Selbst wenn Sie die erste Komponente so konfigurieren könnten, dass sie wie die zweite aussieht, haben Sie eine Abhängigkeitskette geschaffen, die irgendwann bricht, wenn die App Domäne 1 noch anders als Domäne 2 verhalten muss.
Ehrlich gesagt, ich vermeide Custom Properties, es sei denn, es gibt einen ganz bestimmten Anwendungsfall. Wenn eine Sass-Variable die Aufgabe erfüllen kann und sich zur Laufzeit nicht ändert, verwende ich stattdessen diese.
Ich verwende sie, wenn etwas von den Eigenschaften von etwas anderem wissen muss, etwas, das sich zur Laufzeit ändern könnte, z. B.
Ein wenig JavaScript, um
--dynamic-header-heightam Stamm zu aktualisieren, wenn sich die Header-Komponente ändert, kann viele Kopfschmerzen vermeiden. Oder ein absolutes Kind muss seine Elternabmessungen kennen.Custom Properties sind cool, aber die Syntax ist so hässlich und verschmutzend, dass sie, solange es keinen Laufzeitbedarf gibt, weggelassen werden können.
Whoa… ich habe auch ein Video dazu gemacht. Es funktioniert wirklich gut mit AlpineJS. Ich bin zu 55% von diesem Ansatz überzeugt. Ich liebe immer noch Talwind und Assembler CSS, aber für diejenigen, die ihr HTML nicht verschmutzen wollen, könnte Pollen eine gute Lösung sein. https://www.youtube.com/watch?v=Cl2uFIUXqeQ