loading...

CSS Houdini Paint API explained

adrianbdesigns profile image Adrian Bece Originally published at smashingmagazine.com ・4 min read

A Practical Overview Of CSS Houdini (7 Part Series)

1) CSS Houdini introduction & future of CSS 2) Typed Object Model API & Custom Properties And Values API 3 ... 5 3) CSS Houdini Worklets, Paint API and Font Metrics API 4) CSS Houdini Paint API explained 5) CSS Houdini's Animation API & animation timeline explained 6) CSS Houdini's Layout API explained 7) Using CSS Houdini with Progressive Enhancement & Final Thoughts

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:

  1. Write and register a Paint Worklet using the registerPaint function
  2. Call the Worklet in HTML file or main JavaScript file using CSS.paintWorklet.addModule function
  3. 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 from paint function from inside the CSS.
  • contextOptions: allow or disallow opacity for colors. If set to false, 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 in inputProperties
    • args: an array of input arguments passed in paint 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.

Ripple effect example (uses Ripple Worklet by Google Chrome Labs)

Ripple effect example (uses Ripple Worklet by Google Chrome Labs)

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.

Buy Me A Coffee

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.

A Practical Overview Of CSS Houdini (7 Part Series)

1) CSS Houdini introduction & future of CSS 2) Typed Object Model API & Custom Properties And Values API 3 ... 5 3) CSS Houdini Worklets, Paint API and Font Metrics API 4) CSS Houdini Paint API explained 5) CSS Houdini's Animation API & animation timeline explained 6) CSS Houdini's Layout API explained 7) Using CSS Houdini with Progressive Enhancement & Final Thoughts

Posted on by:

adrianbdesigns profile

Adrian Bece

@adrianbdesigns

React, Frontend, Magento 2 certified developer. Magento PWA Studio contributor. Rock and metal music fan. Reads Dune, sci-fi novels and Calvin & Hobbes. Creates amazing interfaces @ prototyp.digital

Discussion

markdown guide