The CSS Painting API — part of the CSS Houdini umbrella of APIs — allows developers to write JavaScript functions that can draw directly into an element's background, border, or content.
Concepts and usage
Essentially, the CSS Painting API contains functionality allowing developers to create custom values for paint()
, a CSS <image>
function. You can then apply these values to properties like background-image
to set complex custom backgrounds on an element.
For example:
aside {
background-image: paint(myPaintedImage);
}
The API defines a worklet
that can be used to programmatically generate an image that responds to computed style changes. To find out more about how this is used, consult Using the CSS Painting API.
Interfaces
PaintWorkletGlobalScope
-
The global execution context of the paint worklet.
PaintRenderingContext2D
-
Implements a subset of the CanvasRenderingContext2D
API. It has an output bitmap that is the size of the object it is rendering to.
PaintSize
-
Returns the read-only values of the output bitmap's width and height.
Examples
The following example creates a list of items with a background image that rotates between three different colors and three widths. In a supporting browser you will see something like the image below.
To achieve this we'll define two custom CSS properties, --boxColor
and --widthSubtractor
.
The paint worklet
In our worklet, we can reference these custom properties.
registerPaint(
"boxbg",
class {
static get contextOptions() {
return { alpha: true };
}
static get inputProperties() {
return ["--boxColor", "--widthSubtractor"];
}
paint(ctx, size, props) {
ctx.fillStyle = props.get("--boxColor");
ctx.fillRect(
0,
size.height / 3,
size.width * 0.4 - props.get("--widthSubtractor"),
size.height * 0.6,
);
}
},
);
We used the inputProperties()
method in the registerPaint()
class to get the values of two custom properties set on an element that has boxbg
applied to it and then used those within our paint()
function. The inputProperties()
method can return all properties affecting the element, not just custom properties.
Using the paint worklet
HTML
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
<li>item 9</li>
<li>item 10</li>
<li>item 11</li>
<li>item 12</li>
<li>item 13</li>
<li>item 14</li>
<li>item 15</li>
<li>item 16</li>
<li>item 17</li>
<li>item</li>
</ul>
CSS
In our CSS, we define the --boxColor
and --widthSubtractor
custom properties.
li {
background-image: paint(boxbg);
--boxColor: hsl(55 90% 60% / 1);
}
li:nth-of-type(3n) {
--boxColor: hsl(155 90% 60% / 1);
--widthSubtractor: 20;
}
li:nth-of-type(3n + 1) {
--boxColor: hsl(255 90% 60% / 1);
--widthSubtractor: 40;
}
JavaScript
In our <script>
we register the worklet:
CSS.paintWorklet.addModule("boxbg.js");
Result
While you can't play with the worklet's script, you can alter the custom property values in DevTools to change the colors and width of the background image.
Specifications
Browser compatibility
|
Desktop |
Mobile |
|
Chrome |
Edge |
Firefox |
Internet Explorer |
Opera |
Safari |
WebView Android |
Chrome Android |
Firefox for Android |
Opera Android |
Safari on IOS |
Samsung Internet |
CSS_Painting_API |
65 |
79 |
No |
No |
52 |
No |
65 |
65 |
No |
47 |
No |
9.0 |
devicePixelRatio |
65 |
79 |
No |
No |
52 |
No |
65 |
65 |
No |
47 |
No |
9.0 |
registerPaint |
65 |
79 |
No |
No |
52 |
No |
65 |
65 |
No |
47 |
No |
9.0 |
See also