CSS-Variablen, genauer gesagt CSS-benutzerdefinierte Eigenschaften, sind in Chrome 49 verfügbar. Sie können nützlich sein, um Wiederholungen in CSS zu reduzieren, und auch für leistungsstarke Laufzeiteffekte wie das Umschalten von Designs und das potenzielle Erweitern/Polyfilling zukünftiger CSS-Funktionen.
CSS-Unordnung
Beim Design einer Anwendung ist es üblich, eine Reihe von Markenfarben festzulegen, die wiederverwendet werden, um das Erscheinungsbild der App einheitlich zu halten. Leider ist es nicht nur mühsam, diese Farbwerte immer wieder in Ihrem CSS zu wiederholen, sondern auch fehleranfällig. Wenn eine der Farben geändert werden muss, könnten Sie einfach alle Vorkommen suchen und ersetzen. Bei einem großen Projekt kann das aber schnell gefährlich werden.
In letzter Zeit haben viele Entwickler CSS-Präprozessoren wie SASS oder LESS verwendet, die dieses Problem durch die Verwendung von Präprozessvariablen lösen. Diese Tools haben die Produktivität von Entwicklern zwar enorm gesteigert, die verwendeten Variablen haben jedoch einen großen Nachteil: Sie sind statisch und können zur Laufzeit nicht geändert werden. Die Möglichkeit, Variablen zur Laufzeit zu ändern, eröffnet nicht nur Möglichkeiten wie dynamische Anwendungsdesigns, sondern hat auch erhebliche Auswirkungen auf das responsive Design und das Potenzial, zukünftige CSS-Funktionen zu polyfillen. Mit der Veröffentlichung von Chrome 49 sind diese Funktionen jetzt in Form von benutzerdefinierten CSS-Properties verfügbar.
Benutzerdefinierte Eigenschaften – Übersicht
Benutzerdefinierte Eigenschaften bieten zwei neue Funktionen für unsere CSS-Toolbox:
- Die Möglichkeit für einen Autor, einer Property mit einem vom Autor gewählten Namen beliebige Werte zuzuweisen.
- Die Funktion
var()
, mit der ein Autor diese Werte in anderen Eigenschaften verwenden kann.
Hier ist ein kurzes Beispiel, um
:root {
--main-color: #06c;
}
#foo h1 {
color: var(--main-color);
}
--main-color
ist ein vom Autor definiertes benutzerdefiniertes Attribut mit dem Wert #06c. Alle benutzerdefinierten Eigenschaften beginnen mit zwei Bindestrichen.
Die Funktion var()
ruft den Wert der benutzerdefinierten Eigenschaft ab und ersetzt sich selbst damit. Das Ergebnis ist color: #06c;
. Solange die benutzerdefinierte Eigenschaft irgendwo in Ihrem Stylesheet definiert ist, sollte sie für die Funktion var
verfügbar sein.
Die Syntax mag auf den ersten Blick etwas ungewöhnlich aussehen. Viele Entwickler fragen sich: „Warum nicht einfach $foo
für Variablennamen verwenden?“ Dieser Ansatz wurde speziell gewählt, um so flexibel wie möglich zu sein und möglicherweise in Zukunft $foo
-Makros zu ermöglichen.
In diesem Beitrag von Tab Atkins, einem der Autoren der Spezifikation, finden Sie weitere Informationen.
Syntax benutzerdefinierter Eigenschaften
Die Syntax für eine benutzerdefinierte Property ist einfach.
--header-color: #06c;
Bei benutzerdefinierten Eigenschaften wird zwischen Groß- und Kleinschreibung unterschieden. --header-color
und --Header-Color
sind also unterschiedliche benutzerdefinierte Eigenschaften. Auf den ersten Blick mag die Syntax für benutzerdefinierte Eigenschaften einfach erscheinen, sie ist aber tatsächlich recht flexibel. Das ist beispielsweise eine gültige benutzerdefinierte Property:
--foo: if(x > 5) this.width = 10;
Das wäre zwar keine nützliche Variable, da sie in keiner normalen Property gültig wäre, aber sie könnte zur Laufzeit mit JavaScript gelesen und darauf reagiert werden. Das bedeutet, dass benutzerdefinierte Eigenschaften das Potenzial haben, alle möglichen interessanten Techniken zu ermöglichen, die mit den aktuellen CSS-Präprozessoren nicht möglich sind. Wenn Sie also denken: Gähn, ich habe SASS, wen interessiert das…“, dann sollten Sie noch einmal genauer hinsehen. Das sind nicht die Variablen, mit denen Sie normalerweise arbeiten.
Die Kaskade
Benutzerdefinierte Eigenschaften folgen den Standardkaskadenregeln. Sie können also dieselbe Eigenschaft auf verschiedenen Detailebenen definieren.
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
While I got red set directly on me!
<p>I’m red too, because of inheritance!</p>
</div>
Das bedeutet, dass Sie benutzerdefinierte Eigenschaften in Media-Queries verwenden können, um das responsive Design zu unterstützen. Ein Anwendungsfall könnte sein, die Ränder um die wichtigsten Abschnittselemente herum zu vergrößern, wenn die Bildschirmgröße zunimmt:
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Das oben stehende Code-Snippet ist mit den aktuellen CSS-Präprozessoren nicht möglich, da diese keine Variablen innerhalb von Media-Queries definieren können. Diese Funktion bietet viel Potenzial.
Es ist auch möglich, benutzerdefinierte Properties zu haben, deren Wert von anderen benutzerdefinierten Properties abgeleitet wird. Das kann für das Design sehr nützlich sein:
:root {
--primary-color: red;
--logo-text: var(--primary-color);
}
Die Funktion var()
Wenn Sie den Wert einer benutzerdefinierten Property abrufen und verwenden möchten, müssen Sie die Funktion var()
verwenden. Die Syntax für die var()
-Funktion sieht so aus:
var(<custom-property-name> [, <declaration-value> ]? )
Dabei ist <custom-property-name>
der Name eines vom Autor definierten benutzerdefinierten Attributs, z. B. --foo
, und <declaration-value>
ein Fallback-Wert, der verwendet wird, wenn das referenzierte benutzerdefinierte Attribut ungültig ist. Fallback-Werte können eine durch Kommas getrennte Liste sein, die zu einem einzelnen Wert kombiniert wird. Beispiel: var(--font-stack,
"Roboto", "Helvetica");
definiert einen Fallback von "Roboto", "Helvetica"
. Beachten Sie, dass Kurzschreibweisen wie die für „margin“ und „padding“ nicht durch Kommas getrennt werden. Ein geeigneter Fallback für „padding“ würde also so aussehen:
p {
padding: var(--pad, 10px 15px 20px);
}
Mit diesen Fallback-Werten kann ein Komponentenautor defensive Stile für sein Element schreiben:
/* In the component’s style: */
.component .header {
color: var(--header-color, blue);
}
.component .text {
color: var(--text-color, black);
}
/* In the larger application’s style: */
.component {
--text-color: #080;
/* header-color isn’t set,
and so remains blue,
the fallback value */
}
Diese Technik ist besonders nützlich für das Theming von Webkomponenten, die Shadow DOM verwenden, da benutzerdefinierte Eigenschaften Shadow-Grenzen überschreiten können. Ein Autor von Webkomponenten kann ein erstes Design mit Fallback-Werten erstellen und Theming-„Hooks“ in Form von benutzerdefinierten Eigenschaften bereitstellen.
<!-- In the web component's definition: -->
<x-foo>
#shadow
<style>
p {
background-color: var(--text-background, blue);
}
</style>
<p>
This text has a yellow background because the document styled me! Otherwise it
would be blue.
</p>
</x-foo>
/* In the larger application's style: */
x-foo {
--text-background: yellow;
}
Bei der Verwendung von var()
gibt es einige Fallstricke, die Sie beachten sollten. Variablen dürfen keine Eigenschaftsnamen sein. Beispiele:
.foo {
--side: margin-top;
var(--side): 20px;
}
Dies entspricht jedoch nicht der Einstellung von margin-top: 20px;
. Stattdessen ist die zweite Deklaration ungültig und wird als Fehler ausgegeben.
Ebenso können Sie nicht (naiv) einen Wert erstellen, bei dem ein Teil davon durch eine Variable bereitgestellt wird:
.foo {
--gap: 20;
margin-top: var(--gap)px;
}
Auch dies entspricht nicht der Einstellung von margin-top: 20px;
. Um einen Wert zu erstellen, benötigen Sie etwas anderes: die Funktion calc()
.
Werte mit calc() erstellen
Wenn Sie noch nie damit gearbeitet haben, ist die Funktion calc()
ein praktisches kleines Tool, mit dem Sie Berechnungen durchführen können, um CSS-Werte zu ermitteln. Sie wird von allen modernen Browsern unterstützt und kann mit benutzerdefinierten Eigenschaften kombiniert werden, um neue Werte zu erstellen. Beispiel:
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px); /* niiiiice */
}
Mit benutzerdefinierten Eigenschaften in JavaScript arbeiten
Um den Wert einer benutzerdefinierten Eigenschaft zur Laufzeit abzurufen, verwenden Sie die Methode getPropertyValue()
des berechneten CSSStyleDeclaration-Objekts.
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'
Wenn Sie den Wert einer benutzerdefinierten Eigenschaft zur Laufzeit festlegen möchten, verwenden Sie die Methode setProperty()
des CSSStyleDeclaration
-Objekts.
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');
Sie können den Wert der benutzerdefinierten Eigenschaft auch so festlegen, dass er zur Laufzeit auf eine andere benutzerdefinierte Eigenschaft verweist. Verwenden Sie dazu die Funktion var()
in Ihrem Aufruf von setProperty()
.
/* CSS */
:root {
--primary-color: red;
--secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');
Da benutzerdefinierte Eigenschaften in Ihren Stylesheets auf andere benutzerdefinierte Eigenschaften verweisen können, können Sie sich vorstellen, dass dies zu allen möglichen interessanten Laufzeiteffekten führen kann.
Unterstützte Browser
Derzeit werden benutzerdefinierte Eigenschaften von Chrome 49, Firefox 42, Safari 9.1 und iOS Safari 9.3 unterstützt.
Demo
Hier finden Sie ein Beispiel, das Ihnen einen Überblick über die interessanten Techniken gibt, die Sie jetzt dank benutzerdefinierter Eigenschaften nutzen können.
Weitere Informationen
Wenn Sie mehr über benutzerdefinierte Eigenschaften erfahren möchten, hat Philip Walton vom Google Analytics-Team eine Einführung dazu geschrieben, warum er sich auf benutzerdefinierte Eigenschaften freut. Den Fortschritt in anderen Browsern können Sie auf chromestatus.com verfolgen.