CSS Houdini may be the most exciting development in CSS. Houdini is comprised of a number of separate APIs, each shipping to browsers separately, and some that have already shipped (here’s the browser support). The Paint API is one of them. I’m very excited about it and recently started to think about how I can use it in my work.
One way I’ve been able to do that is to use it as a way to avoid reinventing the wheel. We’ll go over that in this post while comparing it with methods we currently use in JavaScript and CSS. (I won’t dig into how to write CSS Houdini because there are great articles like this, this and this.)
Houdini brings modularity and configurations to CSS
The way CSS Houdini works brings two advantages: modularity and configurability. Both are common ways to make our lives as developers easier. We see these concepts often in the JavaScript world, but less-so with CSS world… until now.
Here’s a table the workflows we have for some use cases, comparing traditional CSS with using Houdini. I also added JavaScript for further comparison. You can see CSS Houdini allows us to use CSS more productively, similar to how the JavaScript world had evolved into components.
Traditional CSS | CSS Houdini | JavaScript | |
---|---|---|---|
When we need a commonly used snippets | Write it from scratch or copy-paste from somewhere. | Import a worklet for it. | Import a JS library. |
Customize the snippet for the use case | Manually tweak the value in CSS. | Edit custom properties that the worklet exposes. | Edit configs that the library provides. |
Sharing code | Share code for the raw styles, with comments on how to tweak each piece. | Share the worklet (in the future, to a package management service) and document custom properties. | Share the library to a package management service (like npm) and document how to use and configure it. |
Modularity
With Houdini, you can import a worklet and start to use it with one line of code.
<script>
CSS.paintWorklet.addModule('my-useful-paint-worklet.js');
</script>
This means there’s no need to implement commonly used styles every time. You can have a collection of your own worklets which can be used on any of your projects, or even shared with each other.
If you’re looking for modularity for HTML and JavaScript in additional to styles, then web components is the solution.
It’s very similar to what we already have in the JavaScript world. Most people won’t re-implement commonly used functions, like throttling or deep-copying objects. We simply import libraries, like Lodash.
I can imagine we could have CSS Houdini package management services if the popularity of CSS Houdini takes off, and anyone could import worklets for interesting waterfall layouts, background patterns, complex animation, etc.
Configurability
Houdini works well with CSS variables, which largely empowers itself. With CSS variables, a Houdini worklet can be configured by the user.
.my-element {
background-image: paint(triangle);
--direction: top;
--size: 20px;
}
In the snippet, --direction
and --size
are CSS variables, and they’re used in the triangle
worklet (defined by the author of the triangle
worklet). The user can change the property to update how it displays, even dynamically updating CSS variables in JavaScript.
If we compare it to what we already have in JavaScript again, JavaScript libraries usually have options that can be passed along. For example, we can pass values for speed, direction, size and so on to a carousel library to make it perform the way we want. Offering these APIs at the element level in CSS is very useful.
A Houdini workflow makes my development process much more efficient
Let’s see a complete example of how this whole thing can work together to make development easier. We’ll use a tooltip design pattern as an example. I find myself using this pattern often in different websites, yet somehow re-implement for each new project.
Let’s briefly walk through my old experience:
- OK, I need a tooltip.
- It’s a box, with a triangle on one side. I’ll use a pseudo-element to draw the triangle.
- I can use the transparent border trick to draw the triangle.
- At this time, I most likely dig up my past projects to copy the code. Let me think… this one needs to point up, which side is transparent?
- Oh, the design requires a border for the tooltip. I have to use another pseudo-element and fake a border for the pointing triangle.
- What? They decide to change the direction of the triangle?! OK, OK. I will tweak all the values of both triangles…
It’s not rocket science. The whole process may only take five minutes. But let’s see how it can be better with Houdini.
I built a simple worklet to draw a tooltip, with many options to change its looks. You can download it on GitHub.
Here’s my new process, thanks to Houdini:
- OK, I need a tooltip.
- I’ll import this tooltip worklet and use it.
- Now I’ll modify it using custom properties.
<script>CSS.paintWorklet.addModule('my-tooltip-worklet.js')</script>
<style>
.tooltip-1 {
background-image: paint(tooltip);
padding: calc(var(--triangle-size) * 1px + .5em) 1em 1em;
--round-radius: 0;
--background-color: #4d7990;
--triangle-size: 20;
--position: 20;
--direction: top;
--border-color: #333;
--border-width: 2;
color: #fff;
}
</style>
Here’s a demo! Go ahead and play around with variables!
CSS Houdini opens a door to modularized, configurable styles sharing. I look forward to seeing developers using and sharing CSS Houdini worklets. I’m trying to add more useful examples of Houdini usage. Ping me if you have ideas, or want to contribute to this repo.
It’s a bummer that this article completely ignores Sass and SCSS. I’m yet to encounter a situation where a combination of SCSS and CSS custom properties cannot produce clean and obvious workflow.
Styled-Components provides the same solution, plus it integrated with front-end frameworks.
Every positive mentioned in the article is possible with styled-components.
It is the future of CSS.
Great article!
How is something that’s tied to a JavaScript framework “the future of CSS”?
Bingo.
Lazar, that was my exact thought when reading this article. I don’t see the advantage of being able to modify a modules variables through script.
From the tool tip example, this dangerously blurs separation of concerns
Teams will now have to look in multiple places to see what visual styles are being trumped – and that’s just wrong
Can be handled with OOCSS and modifier/variant classes
If specificity or rule weight is worrisome, use the inverted ITCSS triangle popularized by Harry Roberts
If you are worried about writing variations ahead of time in OOCSS, adopt Atomic practices
What he said – everyone loves their preprocessors
In the end, methodologies + best practices > tooling a few dudes at HP, Microsoft, and Google think we need.
Awesome
I’m afraid that the “modularized” CSS “problem” has already been fixed without (partialy) unsupported JavaScript on the client. CSS Houdini is certainly exciting and promising, but the ”modularity” issue is already solved with classes and a build system.
Why not use styled-components instead?
Because it’s tied to React.
Regarding the customization of the worklet, the custom variables are normal CSS variables, right?
So you configure your worklet using global variables, without scoping or anything to prevent your worklet customization from interfering with CSS variables that are used someplace else in your CSS?
It’s much better than what we have now, but as a programmer, it seems… clunky?
The whole modularization thing is a red herring, unless you don’t care how your website looks… Your client definitely will.
This kind of thing is only useful to component libraries pushing there hard to override, zealous use of !important.
Where’s the consideration for creating single level selector rules… The consideration for maintaining big design systems across projects…
I’m going to be unpopular, but bem it’s the best thing to happen to css. The closer to vanilla css you can keep your styles, the better.
If this has to load from a .js file, does it load after the page has been painted? Is there a flash and then the CSS Houdini repaints?
I found more thorough explanation of how the Houdini will work. Apart from creating custom triangles in CSS there’s way more fun in there!
https://tsh.io/blog/css-houdini-future-frontend-development/
No mention of the fact that you can’t use this for ages since you will need to use the fallback implementation for years to come. A fallback which will take just as much time as the “traditional” method you describe, hence no time saved. And at that point, why use Houdini at all, if the fallback works in all browsers?
Currently, I don’t see Houdini’s strength in the benefits you describe. The benefit I see is that it allows for paint alghoritms currently simply impossible to achieve with CSS. That’s a scenario you can progressively enhance. For example, render a rounded button, yet in bleeding edge browsers, render some weird organic shape button.
Within the coming years, I think it’s a bad idea to implement things you can do right now in CSS, to instead do those in Houdini. It makes no sense.