Signatur
Beschreibung
CSS.paintWorklet gibt das Paint-Worklet der CSS Painting API zurück, die zu CSS Houdini gehört. Mit CSS.paintWorklet.addModule(url) lädt man ein Skript, das über registerPaint(name, klasse) einen eigenen „Painter“ anmeldet. Danach kann man ihn in CSS überall dort mit paint(name) verwenden, wo ein Bild (<image>) erwartet wird, zum Beispiel bei background-image, border-image oder mask-image.
Die paint()-Methode der registrierten Klasse bekommt einen eingeschränkten 2D-Kontext (PaintRenderingContext2D), die Größe des Elements und die Werte der CSS-Eigenschaften, die in static get inputProperties() angegeben sind. So entstehen auflösungsunabhängige Muster, Hintergründe oder Rahmen, die sich automatisch an Größe und Custom Properties anpassen und neu gezeichnet werden, wenn sich diese ändern. Zusätzliche DOM-Knoten oder Canvas-Elemente braucht man dafür nicht.
Das Worklet-Skript läuft in einem eigenen PaintWorkletGlobalScope. Dort gibt es keinen Zugriff auf window, document, Netzwerk-APIs oder Timer. Der Browser kann mehrere Instanzen anlegen und sie jederzeit verwerfen, deshalb sollte paint() keinen Zustand speichern und nur von den übergebenen Eingaben abhängen.
Rückgabewert
Worklet-Objekt für Paint-Worklets. Seine wichtigste Methode ist addModule(moduleURL, options?), die ein Promise<void> zurückgibt.Beispiele
Paint-Worklet laden, mit Feature-Erkennung
// main.js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('/worklets/checkerboard.js')
.then(() => console.log('Paint-Worklet geladen'))
.catch((err) => console.error('Laden fehlgeschlagen:', err));
} else {
// Fallback: statisches Hintergrundbild verwenden
document.documentElement.classList.add('no-paint-api');
}
Worklet-Modul: Schachbrettmuster mit Custom Property
// /worklets/checkerboard.js (läuft im PaintWorkletGlobalScope)
class Checkerboard {
static get inputProperties() {
return ['--checker-size', '--checker-color'];
}
paint(ctx, size, props) {
const cell = parseInt(props.get('--checker-size').toString(), 10) || 16;
ctx.fillStyle = props.get('--checker-color').toString().trim() || '#ccc';
for (let y = 0; y < size.height / cell; y++) {
for (let x = 0; x < size.width / cell; x++) {
if ((x + y) % 2 === 0) ctx.fillRect(x * cell, y * cell, cell, cell);
}
}
}
}
registerPaint('checkerboard', Checkerboard);
Einsatz in CSS und Steuerung per JavaScript
// CSS (z. B. in styles.css):
// .card {
// --checker-size: 20;
// --checker-color: #e0e7ff;
// background-image: url('fallback.png');
// background-image: paint(checkerboard);
// }
const start = async () => {
await CSS.paintWorklet.addModule('/worklets/checkerboard.js');
const card = document.querySelector('.card');
// Wenn sich die Custom Property ändert, wird automatisch neu gezeichnet
card.addEventListener('click', () => {
card.style.setProperty('--checker-size', '40');
});
};
start();
Modul aus einem Blob laden (ohne eigene Datei)
const code = `
registerPaint('diagonal', class {
paint(ctx, { width, height }) {
ctx.strokeStyle = 'tomato';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(0, height);
ctx.lineTo(width, 0);
ctx.stroke();
}
});
`;
const url = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));
await CSS.paintWorklet.addModule(url);
document.body.style.backgroundImage = 'paint(diagonal)';
// Wichtig · Fallstricke
- Browser-Unterstützung: Nur Chromium-basierte Browser (Chrome, Edge, Opera, ab etwa Version 65). Firefox und Safari unterstützen die API nicht. Prüfe deshalb immer mit
'paintWorklet' in CSSund gib in CSS vorher einen Fallback an, etwa eine zweitebackground-image-Deklaration vorpaint(). - Sicherer Kontext: Worklets gibt es nur über HTTPS oder
localhost. Das Modul wird nach CORS-Regeln geladen, fremde Ursprünge brauchen also passende Header. Bei einer strengen CSP müssenscript-srcbzw.worker-srcdie Worklet-URL (oderblob:) erlauben. - Eingeschränkter Kontext:
PaintRenderingContext2Dhat keine Text-Methoden (fillTextusw.) und keingetImageData. Im Worklet gibt es weder DOM nochfetchnochsetTimeout. - Kein Zustand: Der Browser kann Painter-Instanzen beliebig anlegen und verwerfen. Werte, die in Instanzvariablen zwischen
paint()-Aufrufen gespeichert werden, sind nicht verlässlich. - Wert der Eigenschaften: Nicht registrierte Custom Properties kommen als
CSSUnparsedValuean. Für typisierte Werte (z. B.CSSUnitValue) und flüssige Animationen registriert man sie mitCSS.registerProperty()oder@property. addModule()mit derselben URL lädt das Modul nicht erneut. Wird ein Name doppelt mitregisterPaintregistriert, löst das einen Fehler aus.