Ein praktischer Überblick über CSS Houdini

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Houdini, ein Überbegriff für die Sammlung von Browser-APIs, zielt darauf ab, den Webentwicklungsprozess und die Entwicklung von CSS-Standards im Allgemeinen erheblich zu verbessern. Frontend-Entwickler können das CSS mithilfe von JavaScript um neue Funktionen erweitern, sich in die CSS-Rendering-Engine einklinken und dem Browser mitteilen, wie CSS während eines Rendervorgangs angewendet werden soll. Die Browserunterstützung von Houdini wird immer besser und einige APIs sind bereits heute verfügbar, also ist es an der Zeit, sich mit ihnen vertraut zu machen und zu experimentieren. Wir werden einen Blick auf jeden Teil von Houdini werfen, seine aktuelle Browserunterstützung und sehen, wie sie heute mit progressiver Erweiterung verwendet werden können.

Es dauert lange, bis eine neue CSS-Funktion oder Verbesserung von einem ersten Entwurf zu einer vollständig unterstützten und stabilen CSS-Funktion entwickelt wird, die Entwickler verwenden können. JavaScript-basierte Polyfills können als Ersatz für die fehlende Browserunterstützung verwendet werden, um neue CSS-Funktionen zu nutzen, bevor sie offiziell implementiert werden. Aber sie sind in den meisten Fällen fehlerhaft. Beispielsweise ist scrollsnap-polyfill eines von mehreren Polyfills, die verwendet werden können, um Inkonsistenzen bei der Browserunterstützung für die CSS Scroll Snap-Spezifikation zu beheben. Aber auch diese Lösung hat einige Einschränkungen, Fehler und Inkonsistenzen.

Der potenzielle Nachteil der Verwendung von Polyfills besteht darin, dass sie sich negativ auf die Leistung auswirken können und schwierig richtig zu implementieren sind. Dieser Nachteil hängt mit dem DOM und CSSOM des Browsers zusammen. Der Browser erstellt ein DOM (Document Object Model) aus HTML-Markup und in ähnlicher Weise erstellt er CSSOM (CSS Object Model) aus CSS-Markup. Diese beiden Objektbäume sind voneinander unabhängig. JavaScript funktioniert auf DOM und hat nur sehr eingeschränkten Zugriff auf CSSOM.

JavaScript-Polyfill-Lösungen werden erst ausgeführt, nachdem der anfängliche Renderzyklus abgeschlossen wurde, dh wenn sowohl DOM als auch CSSOM erstellt wurden und das Dokument vollständig geladen wurde. Nachdem Polyfill Änderungen an Stilen im DOM vorgenommen hat (durch Inlining), wird der Rendervorgang erneut ausgeführt und die gesamte Seite wird erneut gerendert. Negative Auswirkungen auf die Leistung werden noch deutlicher, wenn sie sich auf die requestAnimationFrame Methode verlassen oder von Benutzerinteraktionen wie Scroll-Ereignissen abhängen.

Ein weiteres Hindernis bei der Webentwicklung sind verschiedene Einschränkungen, die durch die CSS-Standards auferlegt werden . Beispielsweise gibt es nur eine begrenzte Anzahl von CSS-Eigenschaften, die nativ animiert werden können. CSS weiß, wie man Farben nativ animiert, aber nicht, wie man Farbverläufe animiert. Es bestand schon immer die Notwendigkeit, innovativ zu sein und beeindruckende Weberlebnisse zu schaffen, indem man trotz der technischen Einschränkungen die Grenzen verschiebt. Aus diesem Grund tendieren Entwickler oft dazu, weniger ideale Problemumgehungen oder JavaScript zu verwenden, um fortschrittlichere Stile und Effekte zu implementieren, die derzeit nicht von CSS unterstützt werden, wie z. gestylte select -Elemente usw.

Es scheint unmöglich, dass CSS-Spezifikationen mit den verschiedenen Funktionsanforderungen der Branche Schritt halten können , wie z. B. mehr Kontrolle über Animationen, verbesserte Textkürzung, bessere Gestaltungsoptionen für input und select , mehr display , mehr filter usw.

Was könnte die mögliche Lösung sein? Bieten Sie Entwicklern eine native Möglichkeit, CSS mithilfe verschiedener APIs zu erweitern . In diesem Artikel werfen wir einen Blick darauf, wie Frontend-Entwickler dies mit Houdini-APIs, JavaScript und CSS tun können. In jedem Abschnitt werden wir jede API einzeln untersuchen, ihre Browserunterstützung und den aktuellen Spezifikationsstatus überprüfen und sehen, wie sie heute mit progressiver Erweiterung implementiert werden können.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Was ist Houdini?

Houdini, ein Überbegriff für die Sammlung von Browser-APIs, zielt darauf ab, den Webentwicklungsprozess und die Entwicklung von CSS-Standards im Allgemeinen erheblich zu verbessern. Entwickler können das CSS mithilfe von JavaScript um neue Funktionen erweitern, sich in die CSS-Rendering-Engine einklinken und dem Browser mitteilen, wie CSS während eines Rendervorgangs angewendet werden soll. Dies führt zu einer deutlich besseren Leistung und Stabilität als bei der Verwendung von regulären Polyfills.

Die Houdini-Spezifikation besteht aus zwei API-Gruppen – High-Level-APIs und Low-Level-APIs .

High-Level-APIs sind eng mit dem Rendering-Prozess des Browsers verbunden (Stil → Layout → Farbe → Composite). Das beinhaltet:

  • Paint-API
    Ein Erweiterungspunkt für den Paint-Rendering-Schritt des Browsers, in dem visuelle Eigenschaften (Farbe, Hintergrund, Rahmen usw.) bestimmt werden.
  • Layout-API
    Ein Erweiterungspunkt für den Layout-Rendering-Schritt des Browsers, in dem Elementabmessungen, Position und Ausrichtung bestimmt werden.
  • Animations-API
    Ein Erweiterungspunkt für den zusammengesetzten Rendering-Schritt des Browsers, bei dem Ebenen auf den Bildschirm gezeichnet und animiert werden.

Low-Level-APIs bilden eine Grundlage für High-Level-APIs. Das beinhaltet:

  • Typisierte Objektmodell-API
  • API für benutzerdefinierte Eigenschaften und Werte
  • Font-Metriken-API
  • Worklets

Einige Houdini-APIs sind bereits für die Verwendung in einigen Browsern verfügbar, andere APIs werden nachziehen, wenn sie zur Veröffentlichung bereit sind.

Die Zukunft von CSS

Im Gegensatz zu herkömmlichen CSS-Funktionsspezifikationen, die bisher eingeführt wurden, zeichnet sich Houdini dadurch aus, dass Entwickler das CSS auf nativere Weise erweitern können. Bedeutet dies, dass sich die CSS-Spezifikationen nicht mehr weiterentwickeln und keine neuen offiziellen Implementierungen von CSS-Funktionen veröffentlicht werden? Nun, das ist nicht der Fall. Houdinis Ziel ist es, den Entwicklungsprozess von CSS-Features zu unterstützen, indem es Entwicklern ermöglicht, funktionierende Prototypen zu erstellen, die leicht standardisiert werden können.

Darüber hinaus können Entwickler die Open-Source-CSS-Worklets einfacher und mit weniger Bedarf an browserspezifischen Bugfixes teilen.

Typisierte Objektmodell-API

Vor der Einführung von Houdini bestand die einzige Möglichkeit für JavaScript, mit CSS zu interagieren, darin, CSS, das als Zeichenfolgenwerte dargestellt wurde, zu analysieren und sie zu ändern. Das manuelle Analysieren und Überschreiben von Stilen kann schwierig und fehleranfällig sein, da der Werttyp hin und her geändert werden muss und die Werteinheit manuell angehängt werden muss, wenn ein neuer Wert zugewiesen wird.

 selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"

Typed Object Model (Typed OM) API fügt CSS-Werten mehr semantische Bedeutung hinzu, indem sie als typisierte JavaScript-Objekte verfügbar gemacht werden. Es verbessert den zugehörigen Code erheblich und macht ihn performanter, stabiler und wartbarer. CSS-Werte werden durch die CSSUnitValue Schnittstelle dargestellt, die aus einem Wert und einer Einheiteneigenschaft besteht.

 { value: 20, unit: "px" }

Diese neue Schnittstelle kann mit den folgenden neuen Eigenschaften verwendet werden:

  • computedStyleMap() : zum Analysieren von berechneten (nicht-inline) Stilen. Dies ist eine Methode des ausgewählten Elements, die vor dem Analysieren oder Verwenden anderer Methoden aufgerufen werden muss.
  • attributeStyleMap : zum Analysieren und Ändern von Inline-Stilen. Dies ist eine Eigenschaft, die für ein ausgewähltes Element verfügbar ist.
 // Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}

Beachten Sie, wie beim Festlegen eines neuen numerischen Werts bestimmte CSS-Typen verwendet werden. Durch die Verwendung dieser Syntax können viele potenzielle typbezogene Probleme vermieden werden und der resultierende Code ist zuverlässiger und fehlerfrei.

Die get und set Methoden sind nur eine kleine Teilmenge aller verfügbaren Methoden, die von der Typed OM-API definiert werden. Einige von ihnen beinhalten:

  • clear : entfernt alle Inline-Stile
  • delete : Entfernt eine angegebene CSS-Eigenschaft und ihren Wert aus Inline-Stilen
  • has : gibt einen booleschen Wert zurück, wenn eine bestimmte CSS-Eigenschaft gesetzt ist
  • append : Fügt einer Eigenschaft, die mehrere Werte unterstützt, einen zusätzlichen Wert hinzu
  • usw.

Feature-Erkennung

 var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }

W3C-Spezifikationsstatus

  • Arbeitsentwurf: zur Überprüfung durch die Community veröffentlicht

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Unterstützt Unterstützt Unterstützt Nicht unterstützt Teilunterstützung (*)

* Unterstützt mit „Experimental Web Platform Features“ oder anderen aktivierten Feature-Flags.

Datenquelle: Ist Houdini schon bereit?

API für benutzerdefinierte Eigenschaften und Werte

Die API für CSS-Eigenschaften und -Werte ermöglicht es Entwicklern, CSS-Variablen zu erweitern, indem sie einen Typ und einen Anfangswert hinzufügen und die Vererbung definieren. Entwickler können benutzerdefinierte CSS-Eigenschaften definieren, indem sie sie mit der Methode registerProperty , die den Browsern mitteilt, wie sie umgestellt werden sollen, und im Falle eines Fehlers mit einem Fallback umgehen.

 CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });

Diese Methode akzeptiert ein Eingabeargument, das ein Objekt mit den folgenden Eigenschaften ist:

  • name : der Name der benutzerdefinierten Eigenschaft
  • syntax : teilt dem Browser mit, wie eine benutzerdefinierte Eigenschaft analysiert werden soll. Dies sind vordefinierte Werte wie <color> , <integer> , <number> , <length> , <percentage> , etc.
  • inherits : teilt dem Browser mit, ob die benutzerdefinierte Eigenschaft den Wert ihres übergeordneten Elements erbt.
  • initialValue : gibt den Anfangswert an, der verwendet wird, bis er überschrieben wird, und dies wird im Falle eines Fehlers als Fallback verwendet.

Im folgenden Beispiel wird die benutzerdefinierte Eigenschaft vom Typ <color> festgelegt. Diese benutzerdefinierte Eigenschaft wird beim Verlaufsübergang verwendet. Sie denken vielleicht, dass das aktuelle CSS keine Übergänge für Hintergrundverläufe unterstützt, und Sie hätten Recht. Beachten Sie, wie die benutzerdefinierte Eigenschaft selbst in transition verwendet wird, anstelle einer background , die für normale background-color verwendet würde.

 .gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }

Der Browser weiß nicht, wie er Farbübergänge handhaben soll, aber er weiß, wie er mit Farbübergängen umgehen soll, da die benutzerdefinierte Eigenschaft als Typ <color> angegeben ist. In einem Browser, der Houdini unterstützt, wird ein Verlaufsübergang ausgeführt, wenn der Mauszeiger über das Element bewegt wird. Der Prozentsatz der Verlaufsposition kann auch durch eine benutzerdefinierte CSS-Eigenschaft (registriert als Typ <percentage> ) ersetzt und auf die gleiche Weise wie im Beispiel zu einem Übergang hinzugefügt werden.

Wenn registerProperty entfernt wird und eine reguläre benutzerdefinierte CSS-Eigenschaft in einem :root Selektor registriert wird, funktioniert der Verlaufsübergang nicht. Es ist erforderlich, dass registerProperty verwendet wird, damit der Browser weiß, dass er es als Farbe behandeln soll.

In der zukünftigen Implementierung dieser API wäre es möglich, eine benutzerdefinierte Eigenschaft direkt in CSS zu registrieren.

 @property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }

Beispiel

Dieses einfache Beispiel zeigt Farbverlauf und Positionsübergang bei Hover-Ereignissen unter Verwendung registrierter benutzerdefinierter CSS-Eigenschaften für Farbe bzw. Position. Der vollständige Quellcode ist im Beispiel-Repository verfügbar.

Animierte Verlaufsfarbe und -position mithilfe der API für benutzerdefinierte Eigenschaften und Werte. Verzögerung für jede Eigenschaft, die für den Effekt in der CSS-Übergangseigenschaft hinzugefügt wurde. (Große Vorschau)

Feature-Erkennung

 if (CSS.registerProperty) { /* ... */ }

W3C-Spezifikationsstatus

  • Arbeitsentwurf: zur Überprüfung durch die Community veröffentlicht

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Unterstützt Unterstützt Unterstützt Nicht unterstützt Nicht unterstützt

Datenquelle: Ist Houdini schon bereit?

Font-Metriken-API

Die Font Metrics API befindet sich noch in einem sehr frühen Entwicklungsstadium, daher kann sich ihre Spezifikation in Zukunft ändern. In ihrem aktuellen Entwurf wird die Font Metrics API Methoden zum Messen der Abmessungen von Textelementen bereitstellen, die auf dem Bildschirm gerendert werden, damit Entwickler beeinflussen können, wie Textelemente auf dem Bildschirm gerendert werden. Diese Werte sind mit den aktuellen Funktionen entweder schwer oder gar nicht zu messen, sodass Entwickler mit dieser API einfacher text- und schriftbezogene CSS-Funktionen erstellen können. Mehrzeiliges dynamisches Abschneiden von Text ist ein Beispiel für eine dieser Funktionen.

W3C-Spezifikationsstatus

  • Ideensammlung: Derzeit kein Spezifikationsentwurf eingereicht

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Nicht unterstützt Nicht unterstützt Nicht unterstützt Nicht unterstützt Nicht unterstützt

Datenquelle: Ist Houdini schon bereit?

Worklets

Bevor wir uns den anderen APIs zuwenden, ist es wichtig, das Worklets-Konzept zu erklären. Worklets sind Skripte, die während des Renderns ausgeführt werden und unabhängig von der Haupt-JavaScript-Umgebung sind. Sie sind ein Erweiterungspunkt für Rendering-Engines. Sie sind auf Parallelität (mit 2 oder mehr Instanzen) und Thread-agnostisch ausgelegt, haben eingeschränkten Zugriff auf den globalen Geltungsbereich und werden bei Bedarf von der Rendering-Engine aufgerufen. Worklets können nur auf HTTPS (in der Produktionsumgebung) oder auf localhost (für Entwicklungszwecke) ausgeführt werden.

Houdini führt die folgenden Worklets ein, um die Browser-Render-Engine zu erweitern:

  • Paint-Worklet – Paint-API
  • Animations-Worklet – Animations-API
  • Layout-Worklet – Layout-API

Paint-API

Die Paint-API ermöglicht Entwicklern die Verwendung von JavaScript-Funktionen, um mithilfe von 2D-Rendering-Kontext, einer Teilmenge der HTML5-Canvas-API, direkt in den Hintergrund, die Umrandung oder den Inhalt eines Elements zu zeichnen. Die Paint-API verwendet Paint Worklet, um ein Bild zu zeichnen, das dynamisch auf Änderungen in CSS reagiert (z. B. Änderungen in CSS-Variablen). Jeder, der mit der Canvas-API vertraut ist, wird sich mit der Paint-API von Houdini wie zu Hause fühlen.

Zur Definition eines Paint Worklets sind mehrere Schritte erforderlich:

  1. Schreiben und registrieren Sie ein Paint Worklet mit der Funktion registerPaint
  2. Rufen Sie das Worklet in der HTML-Datei oder der Haupt-JavaScript-Datei mit der Funktion CSS.paintWorklet.addModule auf
  3. Verwenden Sie die Funktion paint() in CSS mit einem Worklet-Namen und optionalen Eingabeargumenten.

Werfen wir einen Blick auf die Funktion registerPaint , die verwendet wird, um ein Paint Worklet zu registrieren und seine Funktionalität zu definieren.

 registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });

Die Funktion registerPaint besteht aus mehreren Teilen:

  • inputProperties :
    Ein Array von benutzerdefinierten CSS-Eigenschaften, die das Worklet verfolgt. Dieses Array repräsentiert Abhängigkeiten eines Paint Worklets.
  • inputArguments :
    Ein Array von Eingabeargumenten, die von der paint -Funktion innerhalb des CSS übergeben werden können.
  • contextOptions : Opazität für Farben zulassen oder verbieten. Bei false werden alle Farben mit voller Deckkraft dargestellt.
  • paint : die Hauptfunktion, die die folgenden Argumente bereitstellt:
    • ctx : 2D-Zeichnungskontext, fast identisch mit dem 2D-Zeichnungskontext der Canvas-API.
    • size : ein Objekt, das die Breite und Höhe des Elements enthält. Die Werte werden durch den Layout-Rendering-Prozess bestimmt. Die Leinwandgröße entspricht der tatsächlichen Größe des Elements.
    • properties : Eingabevariablen, die in inputProperties definiert sind
    • args : Ein Array von Eingabeargumenten, die in der paint -Funktion in CSS übergeben werden

Nachdem das Worklet registriert wurde, muss es in der HTML-Datei aufgerufen werden, indem einfach ein Pfad zu der Datei bereitgestellt wird.

 CSS.paintWorklet.addModule("path/to/worklet/file.js");

Jedes Worklet kann auch von einer externen URL (z. B. von einem Content Delivery Network) hinzugefügt werden, wodurch es modular und wiederverwendbar wird.

 CSS.paintWorklet.addModule("https://url/to/worklet/file.js");

Nachdem das Worklet aufgerufen wurde, kann es innerhalb von CSS mit der paint -Funktion verwendet werden. Diese Funktion akzeptiert den registrierten Namen des Worklets als erstes Eingabeargument, und jedes darauf folgende Eingabeargument ist ein benutzerdefiniertes Argument, das an ein Worklet übergeben werden kann (in InputArguments des inputArguments definiert). Von diesem Punkt an bestimmt der Browser, wann das Worklet aufgerufen werden soll und auf welche Benutzeraktionen und Wertänderungen der benutzerdefinierten CSS-Eigenschaften reagiert werden soll.

 .exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }

Beispiel

Das folgende Beispiel zeigt die Wiederverwendbarkeit und Modularität der Paint-API und der allgemeinen Worklet-Wiederverwendbarkeit. Es verwendet das Ripple Worklet direkt aus dem Google Chrome Labs-Repository und wird auf einem anderen Element mit unterschiedlichen Stilen ausgeführt. Der vollständige Quellcode ist im Beispiel-Repository verfügbar.

Beispiel für Ripple-Effekt (verwendet Ripple Worklet von Google Chrome Labs) (Große Vorschau)

Feature-Erkennung

 if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }

W3C-Spezifikationsstatus

  • Kandidatenempfehlung: stabiler Arbeitsentwurf bereit zur Umsetzung

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Unterstützt Unterstützt Unterstützt Nicht unterstützt Nicht unterstützt

Datenquelle: Ist Houdini schon bereit?

Animations-API

Die Animations -API erweitert Webanimationen um Optionen zum Anhören verschiedener Ereignisse (Scrollen, Bewegen, Klicken usw.) und verbessert die Leistung, indem Animationen mithilfe eines Animations-Worklets in einem eigenen dedizierten Thread ausgeführt werden. Es ermöglicht Benutzeraktionen, den Animationsfluss zu steuern, der auf performante, nicht blockierende Weise ausgeführt wird.

Wie jedes Worklet muss auch das Animation Worklet zuerst registriert werden.

 registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });

Diese Klasse besteht aus zwei Funktionen:

  • constructor : Wird aufgerufen, wenn eine neue Instanz erstellt wird. Wird für die allgemeine Einrichtung verwendet.
  • animate : die Hauptfunktion, die die Animationslogik enthält. Stellt die folgenden Eingabeargumente bereit:
    • currentTime : der aktuelle Zeitwert aus der definierten Zeitachse
    • effect : eine Reihe von Effekten, die diese Animation verwendet

Nachdem das Animation Worklet registriert wurde, muss es in die Haupt-JavaScript-Datei eingebunden werden, die Animation (Element, Keyframes, Optionen) muss definiert werden und die Animation wird mit der ausgewählten Zeitleiste instanziiert. Timeline-Konzepte und Grundlagen der Webanimation werden im nächsten Abschnitt erläutert.

 /* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */

Timeline-Mapping

Die Webanimation basiert auf Zeitleisten und der Zuordnung der aktuellen Zeit zu einer Zeitleiste der Ortszeit eines Effekts . Schauen wir uns beispielsweise eine sich wiederholende lineare Animation mit 3 Schlüsselbildern (Start, Mitte, Ende) an, die 1 Sekunde nach dem Laden einer Seite (Verzögerung) und mit einer Dauer von 4 Sekunden ausgeführt wird.

Die Effektzeitleiste aus dem Beispiel würde so aussehen (mit einer Dauer von 4 Sekunden ohne Verzögerung):

Effektzeitachse (4s Dauer) Keyframe
0ms Erster Keyframe – Animation beginnt
2000ms Mittlerer Keyframe – Animation läuft
4000ms Letzter Keyframe – Die Animation endet oder wird auf den ersten Keyframe zurückgesetzt

Um effect.localTime besser zu verstehen, wird die resultierende Animation durch Festlegen ihres Werts auf 3000 ms (unter Berücksichtigung einer Verzögerung von 1000 ms) an einen mittleren Keyframe in der Effektzeitachse gebunden (1000 ms Verzögerung + 2000 ms für einen mittleren Keyframe). Der gleiche Effekt tritt auf, wenn Sie den Wert auf 7000 ms und 11000 ms setzen, da die Animation in Intervallen von 4000 ms wiederholt wird (Animationsdauer).

 animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }

Bei einem konstanten effect.localTime Wert findet keine Animation statt, da die Animation in einem bestimmten Keyframe gesperrt ist. Um ein Element richtig zu animieren, muss seine effect.localTime dynamisch sein. Der Wert muss eine Funktion sein, die vom Eingabeargument currentTime oder einer anderen Variablen abhängt.

Der folgende Code zeigt eine funktionale Darstellung einer 1:1-Zuordnung (lineare Funktion) einer Zeitachse, um die Ortszeit zu beeinflussen.

 animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
Zeitleiste ( document.timeline ) Ortszeit des zugeordneten Effekts Keyframe
startTime + 0ms (verstrichene Zeit) startTime + 0ms Zuerst
startTime + 1000ms (verstrichene Zeit) startTime + 1000 ms (Verzögerung) + 0 ms Zuerst
startTime + 3000ms (verstrichene Zeit) startTime + 1000 ms (Verzögerung) + 2000 ms Mitte
startTime + 5000ms (verstrichene Zeit) startTime + 1000 ms (Verzögerung) + 4000 ms Letzte zuerst
startTime + 7000ms (verstrichene Zeit) startTime + 1000 ms (Verzögerung) + 6000 ms Mitte
startTime + 9000ms (verstrichene Zeit) startTime + 1000 ms (Verzögerung) + 8000 ms Letzte zuerst

Die Zeitleiste ist nicht auf die 1:1-Zuordnung zur Ortszeit des Effekts beschränkt. Die Animations-API ermöglicht es Entwicklern, die Zeitachsenzuordnung in der Animationsfunktion zu manipulieren , indem sie Standard- animate -Funktionen verwenden, um komplexe Zeitachsen zu erstellen. Die Animation muss sich auch nicht in jeder Iteration gleich verhalten (wenn die Animation wiederholt wird).

Die Animation muss nicht von der Zeitachse des Dokuments abhängen, die erst ab dem Moment des Ladens mit dem Zählen von Millisekunden beginnt. Benutzeraktionen wie Bildlaufereignisse können mithilfe eines ScrollTimeline Objekts als Zeitachse für Animationen verwendet werden. Beispielsweise kann eine Animation beginnen, wenn ein Benutzer auf 200 Pixel gescrollt hat, und kann enden, wenn ein Benutzer auf einem Bildschirm auf 800 Pixel gescrollt hat.

 const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...

Die Animation passt sich automatisch an die Scrollgeschwindigkeit des Benutzers an und bleibt flüssig und reaktionsschnell. Da Animation Worklets außerhalb des Hauptthreads ausgeführt werden und mit der Rendering-Engine eines Browsers verbunden sind, können Animationen, die vom Scrollen des Benutzers abhängen, reibungslos und sehr leistungsfähig ausgeführt werden.

Beispiel

Das folgende Beispiel zeigt, wie eine nichtlineare Timeline-Implementierung. Es verwendet eine modifizierte Gaußsche Funktion und wendet Translations- und Rotationsanimationen mit derselben Zeitleiste an. Der vollständige Quellcode ist im Beispiel-Repository verfügbar.

Mit der Animations-API erstellte Animation, die eine modifizierte Gaußsche Funktionszeitzuordnung verwendet (große Vorschau)

Feature-Erkennung

 if (CSS.animationWorklet) { /* ... */ }

W3C-Spezifikationsstatus

  • Erster öffentlicher Arbeitsentwurf: bereit für die Überprüfung durch die Community, anfällig für Spezifikationsänderungen

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Teilunterstützung (*) Teilunterstützung (*) Teilunterstützung (*) Nicht unterstützt Nicht unterstützt

* unterstützt mit aktiviertem „Experimental Web Platform Features“-Flag.

Datenquelle: Ist Houdini schon bereit?

Layout-API

Mit der Layout -API können Entwickler den Layout-Rendering-Prozess des Browsers erweitern, indem sie neue Layout-Modi definieren, die in der display -CSS-Eigenschaft verwendet werden können. Die Layout-API führt neue Konzepte ein, ist sehr komplex und bietet viele Optionen für die Entwicklung benutzerdefinierter Layout-Algorithmen.

Ähnlich wie bei anderen Worklets muss das Layout-Worklet zuerst registriert und definiert werden.

 registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });

Das Worklet-Register enthält die folgenden Methoden:

  • inputProperties :
    Ein Array von benutzerdefinierten CSS-Eigenschaften, die das Worklet verfolgt und die zu einem übergeordneten Layoutelement gehören, dh dem Element, das dieses Layout aufruft. Dieses Array repräsentiert Abhängigkeiten eines Layout-Worklets.
  • childrenInputProperties :
    Ein Array von benutzerdefinierten CSS-Eigenschaften, die das Worklet verfolgt und die zu untergeordneten Elementen eines übergeordneten Layout-Elements gehören, dh den untergeordneten Elementen der Elemente, die dieses Layout festlegen.
  • layoutOptions : definiert die folgenden Layouteigenschaften:
    • childDisplay : kann einen vordefinierten Wert von block oder normal haben. Legt fest, ob die Boxen als Blöcke oder inline angezeigt werden.
    • sizing : kann einen vordefinierten Wert von block-like oder manual haben. Es weist den Browser an, die Größe entweder im Voraus zu berechnen oder nicht im Voraus zu berechnen (es sei denn, eine Größe ist explizit festgelegt).
  • intrinsicSizes : definiert, wie eine Box oder ihr Inhalt in einen Layoutkontext passt.
    • children : untergeordnete Elemente eines übergeordneten Layout-Elements, dh die untergeordneten Elemente des Elements, die dieses Layout aufrufen.
    • edges : Layout Kanten einer Box
    • styleMap : typisierte OM-Stile einer Box
  • layout : die Hauptfunktion, die ein Layout ausführt.
    • children : untergeordnete Elemente eines übergeordneten Layout-Elements, dh die untergeordneten Elemente des Elements, die dieses Layout aufrufen.
    • edges : Layout Kanten einer Box
    • constraints : Einschränkungen eines übergeordneten Layouts
    • styleMap : typisierte OM-Stile einer Box
    • breakToken : Unterbrechungstoken, das verwendet wird, um ein Layout im Falle einer Paginierung oder eines Druckvorgangs fortzusetzen.

Wie im Fall einer Paint-API bestimmt die Browser-Rendering-Engine, wann das Paint-Worklet aufgerufen wird. Es muss nur zu einer HTML- oder Haupt-JavaScript-Datei hinzugefügt werden.

 CSS.layoutWorklet.addModule('path/to/worklet/file.js');

Und schließlich muss es in einer CSS-Datei referenziert werden

 .exampleElement { display: layout(exampleLayout); }

Wie die Layout-API das Layout ausführt

Im vorherigen Beispiel wurde exampleLayout mithilfe der Layout-API definiert.

 .exampleElement { display: layout(exampleLayout); }

Dieses Element wird als übergeordnetes Layout bezeichnet, das von Layoutkanten umgeben ist, die aus Polstern, Rahmen und Bildlaufleisten bestehen. Das übergeordnete Layout besteht aus untergeordneten Elementen, die als aktuelle Layouts bezeichnet werden . Aktuelle Layouts sind die eigentlichen Zielelemente, deren Layout mithilfe der Layout-API angepasst werden kann. Zum Beispiel bei Verwendung von display: flex; Auf einem Element werden seine untergeordneten Elemente neu positioniert, um das Flex-Layout zu bilden. Dies ähnelt dem, was mit der Layout-API gemacht wird.

Jedes aktuelle Layout besteht aus einem untergeordneten Layout , das ein Layoutalgorithmus für das LayoutChild ist (Element, ::before und ::after Pseudoelemente) und LayoutChild ist ein CSS-generiertes Feld, das nur Stildaten (keine Layoutdaten) enthält. LayoutChild-Elemente werden automatisch von der Browser-Rendering-Engine im Stilschritt erstellt. Layout Child kann ein Fragment generieren, das tatsächlich Layout-Rendering-Aktionen durchführt.

Beispiel

Ähnlich wie beim Paint-API-Beispiel importiert dieses Beispiel ein Mauerwerk-Layout-Worklet direkt aus dem Google Chrome Labs-Repository, aber in diesem Beispiel wird es mit Bildinhalten anstelle von Text verwendet. Der vollständige Quellcode ist im Beispiel-Repository verfügbar.

Masonry-Layout-Beispiel (verwendet Masonry Worklet von Google Chrome Labs (große Vorschau)

Feature-Erkennung

 if (CSS.layoutWorklet) { /* ... */ }

W3C-Spezifikationsstatus

  • Erster öffentlicher Arbeitsentwurf: bereit für die Überprüfung durch die Community, anfällig für Spezifikationsänderungen

Browser-Unterstützung

Google Chrome Microsoft Edge Opera-Browser Feuerfuchs Safari
Teilunterstützung (*) Teilunterstützung (*) Teilunterstützung (*) Nicht unterstützt Nicht unterstützt

* unterstützt mit aktiviertem „Experimental Web Platform Features“-Flag.

Datenquelle: Ist Houdini schon bereit?

Houdini und progressive Verbesserung

Obwohl CSS Houdini noch keine optimale Browserunterstützung hat, kann es heute mit Blick auf eine progressive Erweiterung verwendet werden. Wenn Sie mit Progressive Enhancement nicht vertraut sind, lohnt es sich, diesen praktischen Artikel zu lesen, der es wirklich gut erklärt. Wenn Sie sich heute für die Implementierung von Houdini in Ihrem Projekt entscheiden, gibt es einige Dinge zu beachten:

  • Verwenden Sie die Feature-Erkennung, um Fehler zu vermeiden.
    Jede Houdini API und jedes Worklet bietet eine einfache Möglichkeit zu prüfen, ob es im Browser verfügbar ist. Verwenden Sie die Funktionserkennung, um Houdini-Verbesserungen nur auf Browser anzuwenden, die sie unterstützen, und vermeiden Sie Fehler.
  • Verwenden Sie es nur zur Präsentation und visuellen Verbesserung.
    Benutzer, die eine Website mit einem Browser besuchen, der Houdini noch nicht unterstützt, sollten Zugriff auf den Inhalt und die Kernfunktionalität der Website haben. Die Benutzererfahrung und die Inhaltsdarstellung sollten nicht von Houdini-Funktionen abhängen und einen zuverlässigen Fallback haben.
  • Verwenden Sie ein Standard-CSS-Fallback.
    Beispielsweise können reguläre benutzerdefinierte CSS-Eigenschaften als Fallback für Stile verwendet werden, die mit der API für benutzerdefinierte Eigenschaften und Werte definiert wurden.

Konzentrieren Sie sich zunächst auf die Entwicklung einer leistungsstarken und zuverlässigen Website-Benutzererfahrung und verwenden Sie dann Houdini-Funktionen für dekorative Zwecke als progressive Verbesserung.

Fazit

Houdini-APIs werden es Entwicklern endlich ermöglichen, den JavaScript-Code, der für die Stilmanipulation und -dekoration verwendet wird, näher an der Rendering-Pipeline des Browsers zu halten, was zu einer besseren Leistung und Stabilität führt. Indem Entwicklern ermöglicht wird, sich in den Browser-Rendering-Prozess einzuklinken, können sie verschiedene CSS-Polyfills entwickeln, die einfach gemeinsam genutzt, implementiert und möglicherweise zur CSS-Spezifikation selbst hinzugefügt werden können. Houdini wird auch Entwickler und Designer bei der Arbeit an Styling, Layouts und Animationen weniger durch die CSS-Einschränkungen einschränken lassen, was zu neuen reizvollen Web-Erlebnissen führt.

CSS Houdini-Features können heute zu Projekten hinzugefügt werden, jedoch ausschließlich unter Berücksichtigung der fortschreitenden Verbesserung. Dadurch können Browser, die Houdini-Funktionen nicht unterstützen, die Website fehlerfrei darstellen und ein optimales Benutzererlebnis bieten.

Es wird spannend sein zu sehen, was die Entwickler-Community sich einfallen lassen wird, wenn Houdini an Zugkraft und besserer Browser-Unterstützung gewinnt. Hier sind einige großartige Beispiele für Houdini-API-Experimente aus der Community:

  • CSS Houdini-Experimente
  • Interaktive Einführung in CSS Houdini
  • Houdini-Beispiele von Google Chrome Labs

Verweise

  • W3C Houdini-Spezifikationsentwürfe
  • Bundesstaat Houdini (Chrome Dev Summit 2018)
  • Animations-Worklet von Houdini – Google Developers
  • Interaktive Einführung in CSS Houdini