Es ist an der Zeit, benutzerdefinierte CSS-Eigenschaften zu verwenden
Veröffentlicht: 2022-03-10Wir verwenden Präprozessoren, um Farben, Schriftarteinstellungen und Layoutdetails zu speichern – fast alles, was wir in CSS verwenden.
Eine detaillierte Einführung in benutzerdefinierte Elemente
Sie haben wahrscheinlich schon von Webkomponenten gehört und wie sie die Webentwicklung für immer verändern werden. Die transformativste Technologie von ist Custom Elements, eine Methode zur Definition Ihrer eigenen Elemente mit ihrem eigenen Verhalten und ihren eigenen Eigenschaften. Lesen Sie die Einführung →
Präprozessorvariablen haben jedoch einige Einschränkungen:
- Sie können sie nicht dynamisch ändern.
- Sie kennen die Struktur des DOM nicht.
- Sie können nicht von JavaScript gelesen oder geändert werden.
Als Wunderwaffe für diese und andere Probleme erfand die Community benutzerdefinierte CSS-Eigenschaften. Im Wesentlichen sehen und funktionieren diese wie CSS-Variablen, und ihre Funktionsweise spiegelt sich in ihrem Namen wider.
Benutzerdefinierte Eigenschaften eröffnen neue Horizonte für die Webentwicklung.
Syntax zum Deklarieren und Verwenden von benutzerdefinierten Eigenschaften
Das übliche Problem, wenn Sie mit einem neuen Präprozessor oder Framework beginnen, besteht darin, dass Sie eine neue Syntax lernen müssen.
Jeder Präprozessor erfordert eine andere Art, Variablen zu deklarieren. Normalerweise beginnt es mit einem reservierten Symbol – zum Beispiel $
in Sass und @
in LESS.
Benutzerdefinierte CSS-Eigenschaften sind den gleichen Weg gegangen und verwenden --
, um eine Deklaration einzuleiten. Aber das Gute daran ist, dass Sie diese Syntax einmal lernen und in verschiedenen Browsern wiederverwenden können!
Sie fragen sich vielleicht: „Warum nicht eine vorhandene Syntax wiederverwenden?“
Es gibt einen Grund. Kurz gesagt, es soll eine Möglichkeit bieten, benutzerdefinierte Eigenschaften in jedem Präprozessor zu verwenden. Auf diese Weise können wir benutzerdefinierte Eigenschaften bereitstellen und verwenden, und unser Präprozessor kompiliert sie nicht, sodass die Eigenschaften direkt an das ausgegebene CSS gehen. Und Sie können Präprozessorvariablen in den nativen Variablen wiederverwenden, aber das werde ich später beschreiben.
(In Bezug auf den Namen: Da ihre Ideen und Zwecke sehr ähnlich sind, werden benutzerdefinierte Eigenschaften manchmal als CSS-Variablen bezeichnet, obwohl der korrekte Name benutzerdefinierte CSS-Eigenschaften lautet, und wenn Sie weiterlesen, werden Sie verstehen, warum dieser Name sie am besten beschreibt.)
Um also eine Variable anstelle einer üblichen CSS-Eigenschaft wie color
oder padding
zu deklarieren, geben Sie einfach eine Eigenschaft mit benutzerdefiniertem Namen an, die mit --
beginnt:
.box{ --box-color: #4d4e53; --box-padding: 0 10px; }
Der Wert einer Eigenschaft kann jeder gültige CSS-Wert sein: eine Farbe, ein String, ein Layoutwert, sogar ein Ausdruck.
Hier sind Beispiele für gültige benutzerdefinierte Eigenschaften:
:root{ --main-color: #4d4e53; --main-bg: rgb(255, 255, 255); --logo-border-color: rebeccapurple; --header-height: 68px; --content-padding: 10px 20px; --base-line-height: 1.428571429; --transition-duration: .35s; --external-link: "external link"; --margin-top: calc(2vh + 20px); /* Valid CSS custom properties can be reused later in, say, JavaScript. */ --foo: if(x > 5) this.width = 10; }
Falls Sie sich nicht sicher sind, was mit :root
übereinstimmt, ist es in HTML dasselbe wie html
, jedoch mit einer höheren Spezifität.
Wie bei anderen CSS-Eigenschaften kaskadieren benutzerdefinierte auf die gleiche Weise und sind dynamisch. Das bedeutet, dass sie jederzeit geändert werden können und die Änderung vom Browser entsprechend verarbeitet wird.
Um eine Variable zu verwenden, müssen Sie die CSS-Funktion var()
verwenden und den Namen der darin enthaltenen Eigenschaft angeben:
.box{ --box-color:#4d4e53; --box-padding: 0 10px; padding: var(--box-padding); } .box div{ color: var(--box-color); }
Deklaration und Anwendungsfälle
Die Funktion var()
ist eine praktische Möglichkeit, einen Standardwert bereitzustellen. Sie können dies tun, wenn Sie nicht sicher sind, ob eine benutzerdefinierte Eigenschaft definiert wurde, und einen Wert angeben möchten, der als Fallback verwendet werden soll. Das geht ganz einfach, indem man den zweiten Parameter an die Funktion übergibt:
.box{ --box-color:#4d4e53; --box-padding: 0 10px; /* 10px is used because --box-margin is not defined. */ margin: var(--box-margin, 10px); }
Wie zu erwarten, können Sie andere Variablen wiederverwenden, um neue zu deklarieren:
.box{ /* The --main-padding variable is used if --box-padding is not defined. */ padding: var(--box-padding, var(--main-padding)); --box-text: 'This is my box'; /* Equal to --box-highlight-text:'This is my box with highlight'; */ --box-highlight-text: var(--box-text)' with highlight'; }
Operationen: +, -, *, /
Wie wir es von Präprozessoren und anderen Sprachen gewohnt sind, wollen wir beim Arbeiten mit Variablen grundlegende Operatoren verwenden können. Dafür bietet CSS eine calc()
-Funktion, die den Browser veranlasst, einen Ausdruck neu zu berechnen, nachdem eine Änderung am Wert einer benutzerdefinierten Eigenschaft vorgenommen wurde:
:root{ --indent-size: 10px; --indent-xl: calc(2*var(--indent-size)); --indent-l: calc(var(--indent-size) + 2px); --indent-s: calc(var(--indent-size) - 2px); --indent-xs: calc(var(--indent-size)/2); }
Ein Problem erwartet Sie, wenn Sie versuchen, einen Wert ohne Einheit zu verwenden. Auch hier ist calc()
Ihr Freund, denn ohne es wird es nicht funktionieren:
:root{ --spacer: 10; } .box{ padding: var(--spacer)px 0; /* DOESN'T work */ padding: calc(var(--spacer)*1px) 0; /* WORKS */ }
Umfang und Vererbung
Bevor wir über die Gültigkeitsbereiche benutzerdefinierter CSS-Eigenschaften sprechen, erinnern wir uns an die Gültigkeitsbereiche von JavaScript und Präprozessoren, um die Unterschiede besser zu verstehen.
Wir wissen, dass beispielsweise bei JavaScript-Variablen ( var
) ein Gültigkeitsbereich auf die Funktionen beschränkt ist.
Wir haben eine ähnliche Situation mit let
und const
, aber sie sind lokale Variablen im Blockbereich.
Eine closure
in JavaScript ist eine Funktion, die Zugriff auf die Variablen der äußeren (einschließenden) Funktion hat – die Bereichskette. Die Closure hat drei Bereichsketten und hat Zugriff auf Folgendes:
- seinen eigenen Gültigkeitsbereich (dh Variablen, die zwischen seinen geschweiften Klammern definiert sind),
- die Variablen der äußeren Funktion,
- die globalen Variablen.
Die Geschichte mit Präprozessoren ist ähnlich. Nehmen wir Sass als Beispiel, weil es heute wahrscheinlich der beliebteste Präprozessor ist.
Bei Sass haben wir zwei Arten von Variablen: lokal und global.
Eine globale Variable kann außerhalb jedes Selektors oder jeder Konstruktion deklariert werden (z. B. als Mixin). Andernfalls wäre die Variable lokal.
Alle verschachtelten Codeblöcke können auf die einschließenden Variablen zugreifen (wie in JavaScript).
Das bedeutet, dass in Sass die Gültigkeitsbereiche der Variablen vollständig von der Struktur des Codes abhängen.
Benutzerdefinierte CSS-Eigenschaften werden jedoch standardmäßig geerbt und wie andere CSS-Eigenschaften kaskadiert.
Sie können auch keine globale Variable haben, die eine benutzerdefinierte Eigenschaft außerhalb eines Selektors deklariert – das ist kein gültiges CSS. Der globale Geltungsbereich für benutzerdefinierte CSS-Eigenschaften ist eigentlich der Geltungsbereich :root
, woraufhin die Eigenschaft global verfügbar ist.
Lassen Sie uns unser Syntaxwissen nutzen und das Sass-Beispiel an HTML und CSS anpassen. Wir erstellen eine Demo mit nativen benutzerdefinierten CSS-Eigenschaften. Zuerst das HTML:
global <div class="enclosing"> enclosing <div class="closure"> closure </div> </div>
Und hier ist das CSS:
:root { --globalVar: 10px; } .enclosing { --enclosingVar: 20px; } .enclosing .closure { --closureVar: 30px; font-size: calc(var(--closureVar) + var(--enclosingVar) + var(--globalVar)); /* 60px for now */ }
Änderungen an benutzerdefinierten Eigenschaften werden sofort auf alle Instanzen angewendet
Bisher haben wir nicht gesehen, wie sich dies von Sass-Variablen unterscheidet. Lassen Sie uns die Variable jedoch nach ihrer Verwendung neu zuweisen:
Im Fall von Sass hat dies keine Auswirkung:
.closure { $closureVar: 30px; // local variable font-size: $closureVar +$enclosingVar+ $globalVar; // 60px, $closureVar: 30px is used $closureVar: 50px; // local variable }
Siehe Pen css-custom-properties-time-to-start-using 3 von Serg Hospodarets (@malyw) auf CodePen.
In CSS wird der berechnete Wert jedoch geändert, da der Wert für die font-size
aus dem geänderten Wert für –closureVar
neu berechnet wird:
.enclosing .closure { --closureVar: 30px; font-size: calc(var(--closureVar) + var(--enclosingVar) + var(--globalVar)); /* 80px for now, --closureVar: 50px is used */ --closureVar: 50px; }
Siehe Pen css-custom-properties-time-to-start-using 2 von Serg Hospodarets (@malyw) auf CodePen.
Das ist der erste große Unterschied: Wenn Sie den Wert einer benutzerdefinierten Eigenschaft neu zuweisen, berechnet der Browser alle Variablen und calc()
Ausdrücke dort neu, wo er angewendet wird.
Präprozessoren sind sich der Struktur des DOM nicht bewusst
Angenommen, wir wollten die font-size
für den Block verwenden, außer dort, wo die highlighted
Klasse vorhanden ist.
Hier ist der HTML-Code:
<div class="default"> default </div> <div class="default highlighted"> default highlighted </div>
Lassen Sie uns dies mit benutzerdefinierten CSS-Eigenschaften tun:
.highlighted { --highlighted-size: 30px; } .default { --default-size: 10px; /* Use default-size, except when highlighted-size is provided. */ font-size: var(--highlighted-size, var(--default-size)); }
Da das zweite HTML-Element mit der default
die highlighted
Klasse trägt, werden Eigenschaften aus der highlighted
Klasse auf dieses Element angewendet.
In diesem Fall bedeutet dies, dass –highlighted-size: 30px;
angewendet, was wiederum dazu führt, dass die Eigenschaft font-size
, die zugewiesen wird, die Eigenschaft –highlighted-size
verwendet.
Alles ist einfach und funktioniert:
Siehe Pen css-custom-properties-time-to-start-using 4 von Serg Hospodarets (@malyw) auf CodePen.
Versuchen wir nun, dasselbe mit Sass zu erreichen:
.highlighted { $highlighted-size: 30px; } .default { $default-size: 10px; /* Use default-size, except when highlighted-size is provided. */ @if variable-exists(highlighted-size) { font-size: $highlighted-size; } @else { font-size: $default-size; } }
Das Ergebnis zeigt, dass die Standardgröße auf beide angewendet wird:
Siehe Pen css-custom-properties-time-to-start-using 5 von Serg Hospodarets (@malyw) auf CodePen.
Dies geschieht, weil alle Sass-Berechnungen und -Verarbeitungen zur Kompilierzeit stattfinden und es natürlich nichts über die Struktur des DOM weiß, da es sich vollständig auf die Struktur des Codes verlässt.
Wie Sie sehen können, haben benutzerdefinierte Eigenschaften die Vorteile des Bereichs von Variablen und fügen die übliche Kaskadierung von CSS-Eigenschaften hinzu, wobei sie sich der Struktur des DOM bewusst sind und denselben Regeln wie andere CSS-Eigenschaften folgen.
Die zweite Erkenntnis ist, dass benutzerdefinierte CSS-Eigenschaften die Struktur des DOM kennen und dynamisch sind .
CSS-weite Schlüsselwörter und die all
-Eigenschaft
Benutzerdefinierte CSS-Eigenschaften unterliegen denselben Regeln wie die üblichen benutzerdefinierten CSS-Eigenschaften. Das bedeutet, dass Sie ihnen jedes der gängigen CSS-Schlüsselwörter zuweisen können:
-
inherit
Dieses CSS-Schlüsselwort wendet den Wert des übergeordneten Elements an. -
initial
Dies wendet den Anfangswert an, wie er in der CSS-Spezifikation definiert ist (ein leerer Wert oder nichts in einigen Fällen von benutzerdefinierten CSS-Eigenschaften). -
unset
Dies wendet den vererbten Wert an, wenn eine Eigenschaft normalerweise vererbt wird (wie im Fall von benutzerdefinierten Eigenschaften), oder den Anfangswert, wenn die Eigenschaft normalerweise nicht vererbt wird. -
revert
Dadurch wird die Eigenschaft auf den Standardwert zurückgesetzt, der vom Stylesheet des Benutzeragenten festgelegt wurde (ein leerer Wert im Fall von benutzerdefinierten CSS-Eigenschaften).
Hier ist ein Beispiel:
.common-values{ --border: inherit; --bgcolor: initial; --padding: unset; --animation: revert; }
Betrachten wir einen anderen Fall. Angenommen, Sie möchten eine Komponente erstellen und sicherstellen, dass keine anderen Stile oder benutzerdefinierten Eigenschaften versehentlich darauf angewendet werden (in einem solchen Fall würde normalerweise eine modulare CSS-Lösung für Stile verwendet).
Aber jetzt gibt es einen anderen Weg: die all
-CSS-Eigenschaft zu verwenden. Diese Abkürzung setzt alle CSS-Eigenschaften zurück.
Zusammen mit CSS-Schlüsselwörtern können wir Folgendes tun:
.my-wonderful-clean-component{ all: initial; }
Dadurch werden alle Stile für unsere Komponente zurückgesetzt.
Leider setzt das Schlüsselwort all
keine benutzerdefinierten Eigenschaften zurück. Es gibt eine anhaltende Diskussion darüber, ob das Präfix --
hinzugefügt werden soll, das alle benutzerdefinierten CSS-Eigenschaften zurücksetzen würde.
In Zukunft könnte ein vollständiger Reset also folgendermaßen durchgeführt werden:
.my-wonderful-clean-component{ --: initial; /* reset all CSS custom properties */ all: initial; /* reset all other CSS styles */ }
Anwendungsfälle für benutzerdefinierte CSS-Eigenschaften
Es gibt viele Verwendungsmöglichkeiten für benutzerdefinierte Eigenschaften. Ich werde die interessantesten von ihnen zeigen.
Emulieren Sie nicht vorhandene CSS-Regeln
Der Name dieser CSS-Variablen lautet „benutzerdefinierte Eigenschaften“. Warum also nicht, um nicht vorhandene Eigenschaften zu emulieren?
Es gibt viele davon: translateX/Y/Z
, background-repeat-x/y
(immer noch nicht Cross-Browser-kompatibel), box-shadow-color
.
Lassen Sie uns versuchen, den letzten zum Laufen zu bringen. Lassen Sie uns in unserem Beispiel die Farbe des Box-Schattens beim Hover ändern. Wir wollen nur der DRY-Regel folgen (wiederholen Sie sich nicht), also ändern wir, anstatt den gesamten Wert von box-shadow
im Abschnitt :hover
zu wiederholen, einfach seine Farbe. Benutzerdefinierte Eigenschaften zur Rettung:
.test { --box-shadow-color: yellow; box-shadow: 0 0 30px var(--box-shadow-color); } .test:hover { --box-shadow-color: orange; /* Instead of: box-shadow: 0 0 30px orange; */ }
Sehen Sie sich die CSS-Eigenschaft „box-shadow-color“ von Pen Emulating unter Verwendung von benutzerdefinierten CSS-Eigenschaften von Serg Hospodarets (@malyw) auf CodePen an.
Farbthemen
Einer der häufigsten Anwendungsfälle von benutzerdefinierten Eigenschaften sind Farbthemen in Anwendungen. Benutzerdefinierte Eigenschaften wurden erstellt, um genau diese Art von Problem zu lösen. Lassen Sie uns also ein einfaches Farbthema für eine Komponente bereitstellen (die gleichen Schritte könnten für eine Anwendung durchgeführt werden).
Hier ist der Code für unsere Button-Komponente:
.btn { background-image: linear-gradient(to bottom, #3498db, #2980b9); text-shadow: 1px 1px 3px #777; box-shadow: 0px 1px 3px #777; border-radius: 28px; color: #ffffff; padding: 10px 20px 10px 20px; }
Nehmen wir an, wir wollen das Farbthema umkehren.
Der erste Schritt wäre, alle Farbvariablen auf benutzerdefinierte CSS-Eigenschaften zu erweitern und unsere Komponente neu zu schreiben. Das Ergebnis wäre also dasselbe:
.btn { --shadow-color: #777; --gradient-from-color: #3498db; --gradient-to-color: #2980b9; --color: #ffffff; background-image: linear-gradient( to bottom, var(--gradient-from-color), var(--gradient-to-color) ); text-shadow: 1px 1px 3px var(--shadow-color); box-shadow: 0px 1px 3px var(--shadow-color); border-radius: 28px; color: var(--color); padding: 10px 20px 10px 20px; }
Das hat alles, was wir brauchen. Damit können wir die Farbvariablen mit den invertierten Werten überschreiben und bei Bedarf anwenden. Wir könnten zum Beispiel die globale inverted
HTML-Klasse hinzufügen (zum Beispiel zum body
-Element) und die Farben ändern, wenn sie angewendet wird:
body.inverted .btn{ --shadow-color: #888888; --gradient-from-color: #CB6724; --gradient-to-color: #D67F46; --color: #000000; }
Unten sehen Sie eine Demo, in der Sie auf eine Schaltfläche klicken können, um eine globale Klasse hinzuzufügen und zu entfernen:
Siehe Pen css-custom-properties-time-to-start-using 9 von Serg Hospodarets (@malyw) auf CodePen.
Dieses Verhalten kann in einem CSS-Präprozessor nicht ohne den Overhead des Duplizierens von Code erreicht werden. Mit einem Präprozessor müssten Sie immer die tatsächlichen Werte und Regeln überschreiben, was immer zu zusätzlichem CSS führt.
Mit benutzerdefinierten CSS-Eigenschaften ist die Lösung so sauber wie möglich, und Kopieren und Einfügen wird vermieden, da nur die Werte der Variablen neu definiert werden.
Benutzerdefinierte Eigenschaften mit JavaScript verwenden
Um Daten von CSS an JavaScript zu senden, mussten wir bisher oft auf Tricks zurückgreifen, indem wir CSS-Werte über einfaches JSON in die CSS-Ausgabe geschrieben und dann aus dem JavaScript gelesen haben.
Jetzt können wir einfach mit CSS-Variablen aus JavaScript interagieren und sie lesen und schreiben, indem wir die bekannten .getPropertyValue()
und .setProperty()
verwenden, die für die üblichen CSS-Eigenschaften verwendet werden:
/** * Gives a CSS custom property value applied at the element * element {Element} * varName {String} without '--' * * For example: * readCssVar(document.querySelector('.box'), 'color'); */ function readCssVar(element, varName){ const elementStyles = getComputedStyle(element); return elementStyles.getPropertyValue(`--${varName}`).trim(); } /** * Writes a CSS custom property value at the element * element {Element} * varName {String} without '--' * * For example: * readCssVar(document.querySelector('.box'), 'color', 'white'); */ function writeCssVar(element, varName, value){ return element.style.setProperty(`--${varName}`, value); }
Nehmen wir an, wir haben eine Liste mit Medienabfragewerten:
.breakpoints-data { --phone: 480px; --tablet: 800px; }
Da wir sie nur in JavaScript wiederverwenden wollen – zum Beispiel in Window.matchMedia() – können wir sie einfach aus CSS bekommen:
const breakpointsData = document.querySelector('.breakpoints-data'); // GET const phoneBreakpoint = getComputedStyle(breakpointsData) .getPropertyValue('--phone');
Um zu zeigen, wie benutzerdefinierte Eigenschaften aus JavaScript zugewiesen werden, habe ich eine interaktive 3D-CSS-Cube-Demo erstellt, die auf Benutzeraktionen reagiert.
Es ist nicht sehr schwer. Wir müssen nur einen einfachen Hintergrund hinzufügen und dann fünf Würfelflächen mit den relevanten Werten für die transform
platzieren: translateZ()
, translateY()
, rotateX()
und rotateY()
.
Um die richtige Perspektive zu bieten, habe ich dem Seitenumbruch Folgendes hinzugefügt:
#world{ --translateZ:0; --rotateX:65; --rotateY:0; transform-style:preserve-3d; transform: translateZ(calc(var(--translateZ) * 1px)) rotateX(calc(var(--rotateX) * 1deg)) rotateY(calc(var(--rotateY) * 1deg)); }
Das einzige, was fehlt, ist die Interaktivität. Die Demo sollte die X- und Y-Ansichtswinkel ( –rotateX
und –rotateY
) ändern, wenn sich die Maus bewegt, und sollte hinein- und herauszoomen, wenn die Maus scrollt ( –translateZ
).
Hier ist das JavaScript, das den Trick macht:
// Events onMouseMove(e) { this.worldXAngle = (.5 - (e.clientY / window.innerHeight)) * 180; this.worldYAngle = -(.5 - (e.clientX / window.innerWidth)) * 180; this.updateView(); }; onMouseWheel(e) { /*…*/ this.worldZ += delta * 5; this.updateView(); }; // JavaScript -> CSS updateView() { this.worldEl.style.setProperty('--translateZ', this.worldZ); this.worldEl.style.setProperty('--rotateX', this.worldXAngle); this.worldEl.style.setProperty('--rotateY', this.worldYAngle); };
Wenn der Benutzer jetzt seine Maus bewegt, ändert die Demo die Ansicht. Sie können dies überprüfen, indem Sie Ihre Maus bewegen und mit dem Mausrad hinein- und herauszoomen:
Siehe Pen css-custom-properties-time-to-start-using 10 von Serg Hospodarets (@malyw) auf CodePen.
Im Wesentlichen haben wir nur die Werte der benutzerdefinierten CSS-Eigenschaften geändert. Alles andere (das Drehen und Vergrößern und Verkleinern) wird von CSS erledigt.
Tipp: Eine der einfachsten Möglichkeiten zum Debuggen eines benutzerdefinierten CSS-Eigenschaftswerts besteht darin, seinen Inhalt in CSS-generierten Inhalten anzuzeigen (was in einfachen Fällen funktioniert, z. B. bei Zeichenfolgen), sodass der Browser automatisch den aktuell angewendeten Wert anzeigt:
body:after { content: '--screen-category : 'var(--screen-category); }
Sie können es in der einfachen CSS-Demo überprüfen (kein HTML oder JavaScript). (Ändern Sie die Größe des Fensters, um zu sehen, dass der Browser den geänderten benutzerdefinierten CSS-Eigenschaftswert automatisch widerspiegelt.)
Browser-Unterstützung
Benutzerdefinierte CSS-Eigenschaften werden in allen gängigen Browsern unterstützt:
Das bedeutet, dass Sie sie nativ verwenden können.
Wenn Sie ältere Browser unterstützen müssen, können Sie die Syntax- und Verwendungsbeispiele lernen und mögliche Wege zum parallelen Umschalten oder Verwenden von CSS- und Präprozessorvariablen in Betracht ziehen.
Natürlich müssen wir in der Lage sein, Unterstützung sowohl in CSS als auch in JavaScript zu erkennen, um Fallbacks oder Verbesserungen bereitzustellen.
Das ist ganz einfach. Für CSS können Sie eine @supports
Bedingung mit einer Dummy-Funktionsabfrage verwenden:
@supports ( (--a: 0)) { /* supported */ } @supports ( not (--a: 0)) { /* not supported */ }
In JavaScript können Sie dieselbe benutzerdefinierte Dummy-Eigenschaft mit der statischen Methode CSS.supports()
verwenden:
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0); if (isSupported) { /* supported */ } else { /* not supported */ }
Wie wir gesehen haben, sind benutzerdefinierte CSS-Eigenschaften immer noch nicht in jedem Browser verfügbar. Wenn Sie dies wissen, können Sie Ihre Anwendung schrittweise verbessern, indem Sie prüfen, ob sie unterstützt werden.
Beispielsweise könnten Sie zwei Haupt-CSS-Dateien generieren: eine mit benutzerdefinierten CSS-Eigenschaften und eine zweite ohne sie, in der die Eigenschaften eingebettet sind (wir werden in Kürze erläutern, wie dies zu tun ist).
Laden Sie standardmäßig die zweite. Überprüfen Sie dann einfach JavaScript und wechseln Sie zur erweiterten Version, wenn benutzerdefinierte Eigenschaften unterstützt werden:
<!-- HTML --> <link href="without-css-custom-properties.css" rel="stylesheet" type="text/css" media="all" />
// JavaScript if(isSupported){ removeCss('without-css-custom-properties.css'); loadCss('css-custom-properties.css'); // + conditionally apply some application enhancements // using the custom properties }
Dies ist nur ein Beispiel. Wie Sie unten sehen werden, gibt es bessere Optionen.
So beginnen Sie mit der Verwendung
Laut einer kürzlich durchgeführten Umfrage ist Sass weiterhin der Präprozessor der Wahl für die Entwicklergemeinschaft.
Lassen Sie uns also überlegen, wie Sie mit der Verwendung von benutzerdefinierten CSS-Eigenschaften beginnen oder sich mit Sass darauf vorbereiten können.
Wir haben ein paar Optionen.
1. Checken Sie den Code für den Support manuell ein
Ein Vorteil dieser Methode, den Code manuell einzuchecken, ob benutzerdefinierte Eigenschaften unterstützt werden, ist, dass es funktioniert und wir es jetzt tun können (vergessen Sie nicht, dass wir zu Sass gewechselt sind):
$color: red; :root { --color: red; } .box { @supports ( (--a: 0)) { color: var(--color); } @supports ( not (--a: 0)) { color: $color; } }
Diese Methode hat viele Nachteile, nicht zuletzt, dass der Code kompliziert wird und das Kopieren und Einfügen ziemlich schwer zu warten ist.
2. Verwenden Sie ein Plugin, das das resultierende CSS automatisch verarbeitet
Das PostCSS-Ökosystem bietet heute Dutzende von Plugins. Einige von ihnen verarbeiten benutzerdefinierte Eigenschaften (Inline-Werte) in der resultierenden CSS-Ausgabe und sorgen dafür, dass sie funktionieren, vorausgesetzt, Sie stellen nur globale Variablen bereit (dh Sie deklarieren oder ändern nur benutzerdefinierte CSS-Eigenschaften innerhalb der :root
Auswahl(en)), also ihre Werte lässt sich einfach einbetten.
Ein Beispiel ist postcss-custom-properties.
Dieses Plugin bietet mehrere Vorteile: Es sorgt dafür, dass die Syntax funktioniert; es ist mit der gesamten Infrastruktur von PostCSS kompatibel; und es erfordert nicht viel Konfiguration.
Es gibt jedoch Nachteile. Das Plugin erfordert, dass Sie benutzerdefinierte CSS-Eigenschaften verwenden, sodass Sie keinen Pfad haben, um Ihr Projekt für einen Wechsel von Sass-Variablen vorzubereiten. Außerdem haben Sie nicht viel Kontrolle über die Transformation, da dies erfolgt, nachdem Sass in CSS kompiliert wurde. Schließlich bietet das Plugin nicht viele Debugging-Informationen.
3. css-vars-Mixin
Ich habe begonnen, in den meisten meiner Projekte benutzerdefinierte CSS-Eigenschaften zu verwenden, und habe viele Strategien ausprobiert:
- Wechseln Sie mit cssnext von Sass zu PostCSS.
- Wechseln Sie von Sass-Variablen zu reinen benutzerdefinierten CSS-Eigenschaften.
- Verwenden Sie CSS-Variablen in Sass, um festzustellen, ob sie unterstützt werden.
Aufgrund dieser Erfahrung suchte ich nach einer Lösung, die meine Kriterien erfüllt:
- Es sollte einfach sein, mit Sass zu beginnen.
- Es sollte einfach zu verwenden sein, und die Syntax muss den nativen benutzerdefinierten CSS-Eigenschaften so nahe wie möglich kommen.
- Das Umschalten der CSS-Ausgabe von den eingebetteten Werten auf die CSS-Variablen sollte einfach sein.
- Ein Teammitglied, das mit benutzerdefinierten CSS-Eigenschaften vertraut ist, kann die Lösung verwenden.
- Es sollte eine Möglichkeit geben, Debugging-Informationen zu Grenzfällen bei der Verwendung von Variablen zu erhalten.
Als Ergebnis habe ich css-vars erstellt, ein Sass-Mixin, das Sie auf Github finden können. Wenn Sie es verwenden, können Sie damit beginnen, die Syntax benutzerdefinierter CSS-Eigenschaften zu verwenden.
Verwendung von css-vars Mixin
Um Variable(n) zu deklarieren, verwenden Sie das Mixin wie folgt:
$white-color: #fff; $base-font-size: 10px; @include css-vars(( --main-color: #000, --main-bg: $white-color, --main-font-size: 1.5*$base-font-size, --padding-top: calc(2vh + 20px) ));
Um diese Variablen zu verwenden, verwenden Sie die Funktion var()
:
body { color: var(--main-color); background: var(--main-bg, #f00); font-size: var(--main-font-size); padding: var(--padding-top) 0 10px; }
Auf diese Weise können Sie die gesamte CSS-Ausgabe von einem Ort aus (von Sass) aus steuern und sich mit der Syntax vertraut machen. Außerdem können Sie Sass-Variablen und -Logik mit dem Mixin wiederverwenden.
Wenn alle Browser, die Sie unterstützen möchten, mit CSS-Variablen arbeiten, müssen Sie nur noch Folgendes hinzufügen:
$css-vars-use-native: true;
Anstatt die Variableneigenschaften im resultierenden CSS auszurichten, beginnt das Mixin mit der Registrierung benutzerdefinierter Eigenschaften, und die var()
Instanzen gehen ohne Transformationen zum resultierenden CSS. Das bedeutet, dass Sie vollständig auf benutzerdefinierte CSS-Eigenschaften umgestellt haben und alle besprochenen Vorteile genießen werden.
Wenn Sie die nützlichen Debugging-Informationen aktivieren möchten, fügen Sie Folgendes hinzu:
$css-vars-debug-log: true;
Dadurch erhalten Sie:
- ein Protokoll, wenn eine Variable nicht zugewiesen, aber verwendet wurde;
- ein Protokoll, wenn eine Variable neu zugewiesen wird;
- Informationen, wenn eine Variable nicht definiert ist, aber ein Standardwert übergeben wird, der stattdessen verwendet wird.
Fazit
Jetzt wissen Sie mehr über benutzerdefinierte CSS-Eigenschaften, einschließlich ihrer Syntax, ihrer Vorteile, guten Verwendungsbeispiele und der Interaktion mit ihnen von JavaScript aus.
Sie haben gelernt, wie Sie feststellen können, ob sie unterstützt werden, wie sie sich von CSS-Präprozessorvariablen unterscheiden und wie Sie mit der Verwendung nativer CSS-Variablen beginnen, bis sie browserübergreifend unterstützt werden.
Dies ist der richtige Zeitpunkt, um mit der Verwendung von benutzerdefinierten CSS-Eigenschaften zu beginnen und sich auf ihre native Unterstützung in Browsern vorzubereiten.