Die CSS Paint API ist extrem spannend, nicht nur wegen dessen, was sie ist, sondern auch wegen dessen, was sie repräsentiert: den Beginn einer sehr aufregenden Zeit für CSS. Lassen Sie uns durchgehen, *was* sie ist, *warum* wir sie haben und *wie* wir mit der Nutzung beginnen.
Was ist die CSS Paint API?
Die API ist nur ein Teil einer ganzen Suite neuer Spezifikationen, die alle unter dem Dach dessen fallen, was als CSS Houdini bekannt ist. Houdini gibt Entwicklern im Wesentlichen *niedrigstufigen Zugriff* auf CSS selbst. Kein Scherz.
Die CSS Paint API erlaubt es Ihnen spezifisch, eine paint() Funktion aufzurufen, wo Sie normalerweise einen Wert für ein erwartetes Bild schreiben würden. Ein häufiges Beispiel ist die Eigenschaft background-image, wo Sie die url() Funktion für einen Link zu einer Bilddatei verwenden könnten, so:
area {
background-image: url('assets/myimage.jpg');
}
Die CSS Paint API erlaubt es Ihnen, *anstelle dessen* die paint() Funktion aufzurufen und einen *Paint Worklet* zu übergeben, den Sie über JavaScript definiert haben. Stellen Sie es sich als ein Stück Code vor, das es Ihnen ermöglicht, programmatisch (ziemlich) alles zu zeichnen, was Sie möchten. Und da es JavaScript ist, können Sie es auch dynamisch gestalten. Die API selbst ist der HTML5 <canvas> API sehr ähnlich (und wir werden gleich darauf eingehen, wie das funktioniert).
Das klingt cool, aber kompliziert. Ich bin schon glücklich mit regulären Bildern...
Das ist großartig! Es ist absolut *nichts* falsch daran, reguläre Bilder zu verwenden, wie Sie es bisher getan haben. Nur weil etwas neu und wahrscheinlich cool ist, heißt das nicht, dass wir es sofort für alles verwenden müssen. Bilder sind jedoch statisch, und die Idee, etwas Dynamisches zu generieren, ist verlockend!
Denken wir einen Moment über linear-gradient nach. Es ist extrem leistungsfähig. Ich meine, schauen Sie sich diese hier an. Aber können Sie sich vorstellen, wie viel weniger Arbeit es wäre, diese geschichteten Muster *ohne* mehrere Hintergrundbilder zu erstellen? Nicht nur das, sondern auch die Untersuchung der CSS Paint API sollte Ihnen helfen zu verstehen, wie diese Art von Bildern zur Laufzeit generiert werden, was sehr hilfreich sein kann (und etwas, das wir gleich tun werden).
Was ist mit conic-gradient welches noch keine Browserunterstützung hat (es gibt jetzt etwas Unterstützung, aber der Punkt, den dies zu machen versucht, bleibt bestehen) ... ohne ein Polyfill, versteht sich. Durch die Nutzung der Paint API könnten Sie einen konischen Gradienten und einige Eigenschaften zum Ändern davon erstellen, ganz ähnlich wie in der eigentlichen Spezifikation. Also, in Wirklichkeit würden Sie tatsächlich Ihr eigenes natives Polyfill erstellen. Das ist ziemlich schick!
Denken Sie daran, dass dies alles Teil der größeren CSS Houdini-Gruppe von Funktionen ist. Hier ist ein Zitat aus dem CSS Houdini Wiki
Das Ziel der CSS-TAG Houdini Task Force (CSS Houdini) ist die gemeinsame Entwicklung von Funktionen, die die "Magie" von Styling und Layout im Web erklären.
Klingt gut, oder? Das ist es, und diese neuen Funktionen sollen Entwicklern ermöglichen, die Funktionalität von CSS selbst zu erweitern, bessere Kontrolle, browserübergreifende Unterstützung und Polyfilling zu bieten.
Der Standardisierungsprozess kann eine Weile dauern: vom Vorschlag einer neuen CSS-Funktion über das Schreiben einer Spezifikation bis hin zur Implementierung dieser neuen Spezifikation durch die Browserhersteller. Und da Entwickler oft bestrebt sind, eine neue Funktion so schnell wie möglich zu nutzen, müssen wir bedenken, dass ältere Browser sie möglicherweise nicht unterstützen *und* möglicherweise auch Änderungen an der Spezifikation, wenn sie noch nicht vollständig implementiert ist – und das ganz zu schweigen von den üblichen Feinheiten der browserübergreifenden Implementierung. Houdini könnte hierbei einen großen Beitrag leisten, indem es uns ermöglicht, Browserfunktionalitäten selbst zu implementieren, während wir darauf warten, dass die Hersteller aufholen.
Philip Walton erklärt diese Vorteile von Houdini und mehr in diesem großartigen Artikel auf Smashing Magazine.
Sie können sehen, wie Ana Tudor sie bereits eingesetzt hat, um komplexe Animationen zu erstellen.
Kann ich es also jetzt benutzen?
Ja! Zum Zeitpunkt des Schreibens wird die CSS Paint API nur in Chrome 65 unterstützt, aber hier ist eine Support-Tabelle, die im Laufe der Zeit aktualisiert wird.
Diese Browser-Support-Daten stammen von Caniuse, das mehr Details enthält. Eine Zahl bedeutet, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 65 | Nein | Nein | 79 | Nein |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | Nein | 127 | Nein |
Aber es liegt noch ein langer Weg vor uns.
Unabhängig davon sehen wir uns an, wie wir den Code dafür erstellen. Ich werde dies in drei Phasen unterteilen. Wir werden dabei einige neue JavaScript-Funktionen verwenden, aber der Code ist für Sie da und wir werden jeden Schritt durchgehen.
Schritt 1: Das CSS
Zuerst müssen wir unserem Worklet einen Namen geben und es im CSS aufrufen. Ich nenne es awesomePattern, also würde mein CSS etwa so aussehen:
section {
background-image: url('fallback.png');
background-image: paint(awesomePattern);
};
Wir sind bereit, aber es wird noch nichts passieren.
Schritt 2: Das JavaScript
Nun müssen wir unser Paint Worklet zu unserem Haupt-JavaScript hinzufügen, das eine weitere JavaScript-Datei wie folgt lädt:
CSS.paintWorklet.addModule('patternWorklet.js');
Auch dann wird noch nichts passieren, da es sich in unserer patternWorklet.js-Datei befindet, wo die gesamte Arbeit erledigt wird.
In patternWorklet.js müssen wir eine *Paint Worklet-Klasse* registrieren:
registerPaint('awesomePattern', Shape);
Wir rufen also die Funktion registerPaint() auf und übergeben, wie wir das Paint Worklet nennen wollen, in diesem Fall awesomePattern, und dann eine Referenz auf die Klasse, die wir schreiben werden, in diesem Fall Shape. Denken Sie daran, dies *nach* der Klasse hinzuzufügen, die wir als nächstes definieren werden. Im Gegensatz zum Hoisting von Funktionen in JavaScript *müssen* Sie Klassen definieren, bevor Sie sie verwenden können.
Als Nächstes verwenden wir die ECMAScript2015-Klassensyntax, um eine Klasse zu schreiben, die unseren Hintergrund für uns zeichnet. Da sie nun als Paint Worklet-Klasse registriert ist, erhalten wir einige Dinge kostenlos.
class Shape {
paint(ctx, geom, properties) {
ctx.strokeStyle = 'white';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.arc( 200, 200, 50, 0, 2*Math.PI);
ctx.stroke();
ctx.closePath();
}
}
Im paint-Callback haben wir ctx, geom und properties. ctx ist dasselbe wie ein 2D-Kontext, den wir von einem <canvas>-Element erhalten würden. (Nun, fast: Ein <canvas>-Element erlaubt die Möglichkeit, Pixeldaten zurückzulesen, während dies mit der CSS Paint API nicht möglich ist.) Es erlaubt uns, dieselben Methoden zum Zeichnen zu verwenden, als wären wir auf Canvas. Im obigen Beispiel zeichne ich einfach einen Kreis mit der Funktion arc.
Die ersten beiden Werte der Funktion arc sind die X- und Y-Koordinaten der Position des Kreises, in Pixeln, von der oberen linken Ecke des Elements. Ich möchte jedoch, dass der Kreis zentral ist, und hier sind die geom-Daten nützlich. Sie geben tatsächlich die PaintSize zurück, die die Größe des Bereichs ist, den das Bild normalerweise füllen würde, und wir können auf width und height-Informationen zugreifen, was genau das ist, was ich brauche, um den Kreis zu zentrieren
Siehe Pen Simple Circle: CSS Paint API Example von Rumyra (@Rumyra) auf CodePen.
Großartig, aber das ist ein ziemlich einfaches Beispiel. Tauschen wir den Kreis gegen etwas etwas Beeindruckenderes aus:
Siehe Pen Simple Circle: CSS Paint API Example von Rumyra (@Rumyra) auf CodePen.
Hier habe ich der Klasse eine Methode namens drawStar hinzugefügt, und dort gibt es eine ganze Reihe von Canvas-Funktionen, die das CSS-Tricks-Logo zeichnen.
Schritt Drei: Benutzerdefinierte Eigenschaften
Wir können mehr tun! Wir können die Leistung von CSS-Benutzereigenschaften (auch Variablen genannt) nutzen. Wir alle waren sehr begeistert von ihnen, und das ist einer der Gründe dafür.
Nehmen wir an, ich möchte die Größe oder Farbe unseres CSS-Tricks-Logos ändern können? Nun, wir können diese Parameter als benutzerdefinierte Eigenschaften in unserem CSS hinterlegen und mit dem dritten Teil der Callback-Daten, properties, darauf zugreifen.
Fügen wir unserer CSS eine Eigenschaft --star-scale hinzu, die unser Logo größer und kleiner machen wird, und eine Eigenschaft --star-color, um die Farbe des Logos direkt im CSS einfach zu ändern.
section {
--star-scale: 2;
--star-color: hsla(200, 50%, 50%, 1);
background-image: paint(awesomePattern)
};
Zurück in unserer Paint Worklet-Klasse müssen wir auf diese benutzerdefinierten Eigenschaften zugreifen. Dies tun wir mit der Methode inputProperties, die uns Zugriff auf alle CSS-Eigenschaften und ihre zugewiesenen Werte gibt.
static get inputProperties() { return ['--star-scale','--star-color']; }
Nun können wir darauf innerhalb der paint-Methode zugreifen:
const size = parseInt(properties.get('--shape-size').toString());
...und diesen Wert in unserem Code verwenden. Wenn wir also entweder die Eigenschaften --star-scale oder --start-color in unserem CSS ändern, wird der Hintergrund aktualisiert!

Es ist auch erwähnenswert, dass all Ihre üblichen CSS-background-Eigenschaften wie erwartet funktionieren, z. B. background-size und background-repeat. Das ist gut zu wissen und immer noch sehr nützlich!
Fazit
Das sind ziemlich mächtige Dinge, und nicht nur für benutzerdefinierte Hintergrundbilder. Stellen Sie sich einen halben oder doppelten Rand an Ihrem Element vor. Normalerweise würden Sie die Pseudoelemente ::before oder ::after verwenden, oder vielleicht einen clever durchdachten box-shadow. Nun, Sie könnten das (und mehr) mit der CSS Paint API und der Eigenschaft border-image implementieren.
Diese API bündelt viele coole Funktionen wie Worklets, ECMAScript2015-Klassen und canvas. Außerdem erhalten wir die gesamte Interaktionsebene, die mit JavaScript einhergeht. Sie könnten leicht Ereignisse hinzufügen, um die benutzerdefinierten Eigenschaften und damit das Bild selbst zu aktualisieren, wie dieses Beispiel von Surma, der das Klickereignis nutzt, um innerhalb einer requestAnimationFrame-Funktion Eigenschaften zu aktualisieren und so eine Animation zu erstellen, jedes Mal wenn der Benutzer auf eine Schaltfläche klickt. Es berücksichtigt sogar die Koordinaten des Klicks.
Das mag auf den ersten Blick etwas kompliziert erscheinen, aber schauen wir uns einige der anderen Teile der Houdini-Suite an, die wir noch kennenlernen werden:
- Die CSS Layout API, die es uns ermöglichen sollte, etwas wie
display: layout('myCustomLayout')zu tun, wofür das typische Beispiel ein benutzerdefiniertes Masonry-Layout wäre, aber der Umfang ist *viel* größer. - Die CSS Properties and Values API, die es uns ermöglicht, Typen für benutzerdefinierte Eigenschaften anzugeben.
- Die CSS Animation Worklet API, die die Animationsverarbeitung vom Hauptthread wegnimmt, was zu seidenweichen Animationen führen sollte.
Also, unabhängig davon, ob Sie an dieser speziellen neuen Funktion interessiert sind oder nicht, sie ist Teil einer ganzen Reihe neuer Technologien, die ein großes Maß an Leistung freisetzen werden. Beobachten Sie diese Seite, denn CSS wird bald noch cooler werden!
Das könnte in Zukunft nett sein. Fürs Erste sehe ich eine Möglichkeit, im Grunde dasselbe mit Inline-SVG und SCSS zu tun.
Ich werde Chris' Details zur Funktionsweise von Inline-SVG-URLs nicht wiederholen, aber es genügt zu sagen, dass es einen Weg gibt, wie es in allen aktuellen Browsern (die SVG unterstützen) funktionieren kann.
Ein großer Nachteil von Chris' Methoden ist, dass das SVG URL-codiert sein muss. Das macht es schwer zu bearbeiten. Also habe ich nach einer Lösung gesucht und diesen Pen gefunden, der SCSS verwendet, um die URL-Codierung aus einer Zeichenkette durchzuführen. Dies bedeutet auch, dass Sie SCSS-Variablen verwenden können, so wie CSS-Variablen oben verwendet wurden. Betten Sie sie einfach mit #{$var} in die SVG-Zeichenkette ein.
„Kann ich es also jetzt benutzen? Ja! Die CSS Paint API wird zum Zeitpunkt des Schreibens nur in Chrome 65 unterstützt.“
Das ist eine interessante Definition von „benutzen“. :-) CanIUse.com würde sagen nein.
Ich würde sagen, wir können es *jetzt ausprobieren*, aber wir können es definitiv *nicht jetzt benutzen*, es sei denn, Sie möchten, dass die Hälfte Ihrer Zuschauer es nicht sehen kann.
Hallo Tim!
Ja, ich denke, „Sie können“ ist eine starke Formulierung. Sie können aber einfach
background-image: url('fallback.jpg');als einfaches Fallback verwenden, damit Ihre Benutzer nicht komplett leer ausgehen! :)Toller Artikel! Ich liebe es, einen Vorgeschmack auf all die Leckereien zu bekommen, die Houdini zu bieten hat.
Danke Tim! Ja, das tue ich auch :) Es ist aufregend zu sehen, wie sich die Dinge entwickeln!
Es könnte erwähnenswert sein, dass es ein Polyfill für CSS Paint gibt, das in allen modernen Browsern funktioniert.
https://github.com/GoogleChromeLabs/css-paint-polyfill