As of version 65 Chrome will be the first browser to support the CSS paint api. this is the first part of a set of specs which are collectively called Houdini. Houdini is just as magical as it sounds, because once it has full browser support, it will allow you to “Design your own css styles”.
To give you a sense of what exactly this means, this website contains some samples of intended Houdini functionality. These demo’s actually work best in Firefox.
Disclaimer: The examples embedded here currently only work in Chrome 65+ Paint API
So the first part of this api has been delivered! what can I do now? Well, the first part of the api let’s you do the following:
CSS Paint API allows you to programmatically generate an image whenever a CSS property expects an image. ~Surma
That sounds pretty limited if you read it at first right? Especially if you look at the simple example given at the google developers website. It’s nice we are now able to draw a checkerboard in javascript, but it’s not the magic we were promised.
So how cán we make this more interesting? By combining it with other recent developments in css! Defining our paint worklet
In the following examples, we are using a worklet which draws lines in a regular pattern. This is pretty basic, but it’s a good use case to show the potential of the paint API.
The code below registers our worklet and defines the input parameters which can be adjusted by setting them as CSS variables:
class LinesPainter {
// This getter defines the compatible css variables
static get inputProperties() {
return ["--line-spacing", "--line-size", "--line-color"];
}
paint(ctx, geom, properties) {
// Parse the css variables
const lineSize = parseInt(properties.get("--line-size").toString());
const lineColor = properties.get("--line-color").toString();
const lineSpacing = parseInt(properties.get("--line-spacing").toString());
ctx.strokeStyle = lineColor || "black";
for (let y = 0; y < geom.height; y += lineSpacing) {
for (let x = 0; x < geom.width; x += lineSpacing) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + lineSize, y + lineSize);
ctx.stroke();
}
}
}
}
Using the above worker to render the background of a div gives us the following result: Open in new tab
Using “inspect element” and devTools we can now edit the css variables, which will result in a different picture being rendered as the <div>’s background.
Black looks a bit dull, so we can tweak our css until it looks just right: Open in new tab Adding some sugar on top: Transitions!
So we can use variables to influence our nice drawings, which is nice to iteratively work towards a nice image. Thinking a bit further in this direction, one might wonder:
“But can we also apply transitions to our variables?”
And the answer is: YES!
To do this we actually use another new part of the CSS spec called CSS Properties and values API. This allows us to “type” our custom variables, which in turn allows the browser to choose the correct transition method. You can imagine transitioning a color from red to blue requires a different interpolation method than transitioning from 0 to 100.
A simple example of registering a custom css property looks like this:
CSS.registerProperty({
name: "--line-spacing",
syntax: "<number>",
initialValue: 10,
});
This snippet will register the –line-spacing property as a number which will be 10 by default.
So let’s register all the variables we have defined as input variables for our worklet, and transition between them on hover state for example: Open in new tab
Amazing right? Can you imagine how many lines of code we have saved by leveraging the CSS transition system to interpolate between the various CSS states? As an exercise you can imagine how you would write this using a regular canvas approach.
Although I was sceptical at first, I’m quite impressed with the possibilities the paint API brings for creating completely custom effects while remaining compatible with how CSS works. I hope this example has triggered your imagination about the possibilities the paint API, let me know what you come up with! Want to learn more?
@iamvdo has collected several interesting examples on his CSS houdini website, including some more practical implementations of the paint API.