Rolf B: Houdini - entfesseltes CSS. Teil 1: Eigenschaften und Werte

Die CSS Houdini Initiative existiert seit einigen Jahren, um CSS und JavaScript einander näher zu bringen. Von den geplanten sieben APIs sind mittlerweile drei in Browsern mit Blink-Engine (Chromium) implementiert, Webkit (Safari) arbeitet daran und Gecko (Firefox) denkt darüber nach.

Zeit also, sich diese APIs einmal näher anzuschauen.

Custom Properties[1]

Kennen Sie das hier?

h1 {
   color: var(--head-fg);
   background-color: var(--head-bg);
}

Hier werden Custom Properties verwendet, um die Farben einer h1 Überschrift zu setzen. Lesen Sie kurz im Wiki nach, wenn Ihnen Custom Properties noch unbekannt sind.

Spätestens jetzt wissen Sie auch, dass ein solches Custom Property auch einen Wert benötigt - oder einen Fallback-Wert in der var()-Angabe:

:root {
   --head-fg: white;
   --head-bg: blue;
}

h1 {
   color: var(--head-fg, yellow);
   background-color: var(--head-bg, purple);
}

Da hier für das root-Element des Dokuments (also das <html>-Element) Werte für
--head-fg und --head-bg gesetzt werden, kommen die Default-Angaben nicht zum Zuge.

Aber was ist hiermit?

:root {
   --head-bg: blu;
}

Gleich zwei Fehler: --head-fg wurde vergessen, und die Farbe blu gibt es nicht. Die Folge? Für color greift der Defaultwert in der var()-Funktion, und für background-color der von sonstwoher vererbte Wert. Im Zweifelsfalle also weiß.

Es ist ja schön und gut, dass wir unsere eigenen Eigenschaften erfinden dürfen, aber es wäre schöner und besser, wenn wir auch festlegen könnten, wie sie auszusehen haben.

Gestatten, mein Name ist Houdini

Das Eigenschaften und Werte API (Properties and Values Level 1) bietet genau das. Sie können für Custom Properties festlegen, welchen Syntaxregeln sie zu folgen haben. Für unsere beiden Farben könnten wir das so lösen:

@property --head-fg {
   syntax: "<color>";
   inherits: true;
   initial-value: white;
}
@property --head-bg {
   syntax: "<color>";
   inherits: true;
   initial-value: #c32e04;
}

Damit legen wir fest, dass diese beiden Eigenschaften genau eine Farbe erwarten, dass ihr Wert an Kind-Elemente vererbt wird und welcher Wert verwendet werden soll, wenn die Eigenschaft nicht explizit gesetzt wurde.

Das schlägt zwei Fliegen mit einer Klappe: Wir können für unser Default-Farbschema auf eine Liste von Farbdefinitionen verzichten (nun gut, um den Preis einer Menge von @property-Definitionen), und wir brauchen an den Stellen, wo diese Custom Properties mit var() angesprochen werden, keinen Defaultwert für den Fall anzugeben, dass die Eigenschaft nicht gesetzt ist. Und wenn jemand blu als Farbe angibt, dann erkennt der Browser, dass das kein erlaubter Farbwert ist, und ignoriert die Angabe, statt sie im Custom Property zu speichern und dessen Nutzer darüber stolpern zu lassen.

Die möglichen Angaben für eine Syntax finden Sie im Abschnitt 5 - Syntax der Spezifikation. Es gibt etliche Typnamen, wie <color> für Farbwerte, <length> für Längenangaben, <number> für beliebige Zahlen und noch einige mehr, entsprechend den möglichen Wertetypen, die für CSS Eigenschaften möglich sind. Es gibt zwei Multiplikatorangaben, nämlich + und #. Das Plus gibt an, dass eine durch Leerzeichen getrennte Liste erwartet wird (was sich bei Kombinationseigenschaften findet) und das # verlangt eine durch Komma getrennte Werteliste, wie z.B. in einer Liste von Fontnamen. Mit dem senkrechten Strich | können Alternativen festgelegt werden, mit "<integer> | auto" würden Sie festlegen, dass die Eigenschaft einen ganzzahligen Wert oder das Schlüsselwort auto annehmen darf.

Propertydefinitionen in JavaScript

Außer mit @property-Angaben in einem Stylesheet können Sie Eigenschaften auch mit JavaScript registrieren. Dazu dient die Methode registerProperty des CSS Objekts, der Sie ein Objekt übergeben, das analog zu einer @property-Definition aufgebaut ist:

CSS.registerProperty( {
   name: '--head-fg';
   syntax: '<color>';
   inherits: true;
   initialValue: 'white';
});

Im übrigen hat dieser Teil von Houdini nicht so viel mit JavaScript zu tun. Hier werden aber Grundlagen gelegt, die an anderer Stelle relevant werden.

Animationen

Typsichere Eigenschaftendefinitionen haben noch einen weiteren Vorteil: sie machen Ihre Custom Properties animierbar.

Dieses CSS würde zu einem harten Übergang führen statt zu einer Animation, weil blue und green ohne eine Registrierung der Eigenschaft für den Browser einfach nur beliebige Strings sind:

:root {
   --head-bg: blue;
}
h1 {
   transition: background-color 2s;
   background-color: var(--head-bg);
}

h1:hover {
   --head-bg: green;
}

Aber so:

@property --head-bg {
   syntax: "<color>";
   initial-value: #c32e04;
   inherits: true; 
}
h1 {
   transition: background-color 2s;
   background-color: var(--head-bg);
}

h1:hover {
   --head-bg: green;
}

erhalten Sie einen sanften Übergang von Selfhtml-Rot zu Grün.

Links


  1. Oder Custom Propertys? Der Duden sagt: der Plural englischer Wörter wird nicht (mehr) auf ies gebildet. Das gilt aber nicht für „Zitatwörter“, die folgen englischen Regeln. Demzufolge sind es also Custom Properties. Gelegentlich brauchte ich aber auch mal „Property“ ohne „Custom“, was ich laut Duden zu „Propertys“ pluralisieren müsste. Das sah sehr verwirrend aus, deshalb habe ich dann konsequent „Eigenschaften“ geschrieben. ↩︎

  1. Klingt sehr interessant, werde ich mal gespannt weiter verfolgen 👍