This post has been originally published on Smashing Magazine and I decided to split it into parts to make it more digestible. I'll be converting the post into markdown and publish a part of it on DEV every week. If you want to read it right away in its entirety, feel free to read it on Smashing Magazine until all parts are available on DEV. Thank you.
Paint API
The Paint API allows developers to use JavaScript functions to draw directly into an element’s background, border, or content using 2D Rendering Context, which is a subset of the HTML5 Canvas API. Paint API uses Paint Worklet to draw an image that dynamically responds to changes in CSS (changes in CSS variables, for example). Anyone familiar with Canvas API will feel right at home with Houdini’s Paint API.
There are several steps required in defining a Paint Worklet:
- Write and register a Paint Worklet using the
registerPaint
function - Call the Worklet in HTML file or main JavaScript file using
CSS.paintWorklet.addModule
function - Use the
paint()
function in CSS with a Worklet name and optional input arguments.
Let’s take a look at the registerPaint
function which is used to register a Paint Worklet and define its functionality.
registerPaint("paintWorketExample", class {
static get inputProperties() { return ["--myVariable"]; }
static get inputArguments() { return ["<color>"]; }
static get contextOptions() { return {alpha: true}; }
paint(ctx, size, properties, args) {
/* ... */
}
});
The registerPaint
function consists of several parts:
-
inputProperties
: An array of CSS custom properties that the Worklet will keep track of. This array represents dependencies of a paint worklet. -
inputArguments
: An array of input arguments that can be passed frompaint
function from inside the CSS. -
contextOptions
: allow or disallow opacity for colors. If set tofalse
, all colors will be displayed with full opacity. -
paint
: the main function that provides the following arguments:-
ctx
: 2D drawing context, almost identical to Canvas API’s 2D drawing context. -
size
: an object containing the width and height of the element. Values are determined by the layout rendering process. Canvas size is the same as the actual size of the element. -
properties
: input variables defined ininputProperties
-
args
: an array of input arguments passed inpaint
function in CSS
-
After the Worklet has been registered, it needs to be invoked in the HTML file by simply providing a path to the file.
CSS.paintWorklet.addModule("path/to/worklet/file.js");
Any Worklet can also be added from an external URL (from a Content Delivery Network, for example) which makes them modular and reusable.
CSS.paintWorklet.addModule("https://url/to/worklet/file.js");
After the Worklet has been called, it can be used inside CSS using the paint
function. This function accepts the Worklet’s registered name as a first input argument and each input argument that follows it is a custom argument that can be passed to a Worklet (defined inside Worklet’s inputArguments
). From that point, the browser determines when to call the Worklet and which user actions and CSS custom properties value change to respond to.
.exampleElement {
/* paintWorkletExample - name of the worklet
blue - argument passed to a Worklet */
background-image: paint(paintWorketExample, blue);
}
Example
The following example showcases Paint API and general Worklet reusability and modularity. It’s using the ripple Worklet directly from Google Chrome Labs repository and runs on a different element with different styles. Complete source code is available on the example repository.
Feature detection
if ("paintWorklet" in CSS) {
/* ... */
}
@supports(background:paint(paintWorketExample)){
/* ... */
}
W3C Specification Status
Candidate recommendation: stable working draft ready for implementation
Browser Support
- Google Chrome: Supported
- Microsoft Edge: Supported
- Opera Browser: Supported
- Firefox: Not supported
- Safari: Not supported
Data source: Is Houdini Ready Yet?
These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.
Thank you for taking the time to read this post. Keep an eye out for the next part in the series. If you've found this useful, please give it a ❤️ or 🦄, share and comment.
Top comments (1)
Cheers🎉🎉🎉🎉