Hallo zusammen! Today I want to tell about my experience with CSS Houdini, what is it and how it works. In particular, I’ll show and tell you about Paint API, this is the part of Houdini CSS.
About a year ago I heard about
CSS Houdini and that it’s a powerful thing and will change the way we build CSS today. But only today, I’ve decided to give it a shot, and I was surprised about the effects that you can achieve with it and also a little disappointed about the feature coverage across browsers.
Because I remember how fast
CSS grid layout was implemented — pretty fast. And I consider
CSS Houdini in the same way — this is the feature that will help designers to achieve effects that is possible today only in graphic/design tools.
What is CSS Houdini 🧐
“Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine”
It means that developers can parse CSSOM, write custom properties and easily manipulate them through JS or CSS.
And Houdini has three basic API to make custom things:
- Paint API — https://developers.google.com/web/updates/2018/01/paintapi
- Animation API — https://developers.google.com/web/updates/2018/10/animation-worklet
- Layout API — https://dev.to/adrianbdesigns/css-houdini-s-layout-api-explained-33pa
Houdini.how | CSS-Tricks
Nice site from Google (and guest contributors) with a bunch of fun demos of what Houdini can do. Plus a write-up from…
Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by…
Find really cool examples here 👇
I found a few really nice Houdini examples that use Pain API and decided to try to make something with it too.
What I really wanted to see on the web today is the ability to use squircles or superellipse shapes instead of the standard
Squircle - Wikipedia
A squircle is a shape intermediate between a square and a circle. There are at least two definitions of "squircle" in…
Squircles on the web today
Before I will dig deep into the module I wrote, let's quickly overview how we can bring squircles experience today.
There are some ways how to implement a squircle shape on the Web, but none of them are native or flexible enough.
This is unfortunate. Also, many of these ways are pretty hacky, which means that each method has some restrictions which are not so good if you want to use it widely.
Current implementation methods
Let’s take a look at two methods and let's take this checklist to make some conclusions about them. The winner is the one with fewer points.
- can’t use as a background image
- use only as separated component
- can’t change Squircle smoothness
- Squircle not scalable
- Can’t outline
- Noticeable artifacts or shape imperfections
1. CSS border-radius hack
This method works, but it’s pretty restricted, is not flexible, and I can’t use it on different elements.
This method scores 6 out of 6 points. I don’t see how I use it as a button or how I’m trying to scale it to different sizes.
2. SVG shape as a background
This is a good method in terms of the shape build, but the manipulation can be done here only through JS.
Read this article (which was written in 2018), this is a pretty detailed investigation:
An easy way to implement smooth shapes (such as Superellipse and Squircle) into a user interface.
Solution for all sizes and colors.
Here are a few playground examples. Check it out 🔭 🕹
A small notebook to generate images of Piet Hein's superellipses. A superellipse is partway between a circle and a…
So, this method scores only 3/6.
We can use outline, effect, change the shape only via JS or only if an element predefined by its size.
Both these methods can’t make two important things that stop me from using them — not flexible. My element should be a square or predefined rectangle.
But here is the case where Paint API will save us. It can easily solve flexibility color, effects, and manipulation issues.
UPD: a cool SVG generator example
Here are two cool examples of squrcle-generators by Mathieu Jouhet 👇
3. Paint API 🎨
What is great in Pain API is that we can write our own custom CSS properties — without involving JS. We can make our effects flexible, which means that we can implement them and scale with any element.
Here is an abstract scheme of how Paint API works:
All good with the example below, it supports negative values and uses a correct script, but it’s not scalable, and I also would like to use cubic-bezier, I use it in Figma and I understand how to build a squircle shape with it.
Build a squircle shape ✏️ 📐️
I wouldn’t describe each line of the module, but I’ll explain the most important parts of it and how I build the shape.
1. Curvature. What is the difference between these two shapes? First is that a squircle shape rounding starts smoothly, while standard rounding always has the same angle (pic.1)
In order to build the curvature, I’ll use bezier-curves. Here is the demonstration, how to build standard and squircle shapes with bezier-curves.
2. Early rounding. 20px radius for a squircle shape is not the same as for the standard one, because smoothing starts earlier. It means that when a user writes e.g. 20px we will need to take a ratio to make values on squircle and standard shape visually the same (pic.2). The example below I made in Figma and you can see that the squircle starts to round earlier, but visually both figures have the same radius.
in my case, the ideal ratio is 1.8. I will add this ratio to the bezier distance.
So, the ratio here means that I wouldn’t draw bezier-lines almost to the very end of corners, but stop them a little earlier — at 0.1 earlier (or 0.2 because we double the input radius). And I’ll multiply my radius at this ratio as well.
The ratio I took doesn’t rely on any math formulas, I just tried to find the ideal number, and I’m pretty good with the 1.8.
But you can also change the default ratio using secret 🤭 custom property
How to draw bezier-curve with canvas ✍️
This is actually pretty simple. First, we need to draw a simple line
lineTo(x,y) and our line will consist of four arguments: x1,y1 → x2,y2
Then we draw the arc with a special method
bezierCurveTo where we have 3 dots. x1,y1 — where the first bezier line ends (x0,y0 was taken from the previous line automatically), x2,y2 — where the second bezier line begins, and x3,y3— where it ends.
So, for instance, if we want to change a standard radius 50%50 to a squircle like, we can change x1 to 190 and y2 to 10.
Prevent dots overlapping ⚡️
--squircle-radius property will be bigger than the figure width or height? We will see something like in picture 3.
What we need to do to avoid overlapping like this is a simple check:
squircleRadius < geom.width / 2 && squircleRadius < geom.height / 2
in this line, we check if width and height lesser than radius divided by 2. If it's bigger, then we need to pass the radius equals to the smaller parameter (width or height). But how do you know which parameter is smaller?
Math.min() method. It will automatically check which value is smaller and return it.
Math.min(geom.width / 2, geom.height / 2)
Grab the full module code here — https://github.com/PavelLaptev/squircle-houdini-css/blob/main/public/paintWorklet/squircle.js
Can I use it?
Here are just some screenshots.
In conclusion and demos
Well… Houdini and Paint API, in particular, is a cool feature, and I hope we can use it on all browsers in the near future. Meanwhile, check this module out here 👇
Squircle CSS Houdini
A tiny CSS Houdini module that allows to add a squircle shape to HTML elements
All links and references from the article
- Scripts in different languages to draw superellipse— rosettacode.org/wiki/Superellipse
- Unleashing Genetic Algorithms on the iOS 7 Icon —blog.mikeswanson.com/post/62341902567/unleashing-genetic-algorithms-on-the-ios-7-icon
- Say Hello to Houdini and the CSS Paint API — codersblock.com/blog/say-hello-to-houdini-and-the-css-paint-api
- bezierCurveTo() method explained — developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo
- Smooth corners Houdini module — css-houdini.rocks/smooth-corners
- Cross-browser paint worklets and Houdini.how — web.dev/houdini-how
- Desperately seeking squircles — www.figma.com/blog/desperately-seeking-squircles
- Stackoverflow question about rounded cube with C++ — stackoverflow.com/questions/27139327/creating-a-rounded-cube-with-bezier-curves
- Bezier-curve online playground — www.desmos.com/calculator/cahqdxeshd
- The service generates SVG squircles — squircley.app