A Houdini Quickstart: registerProperty
Houdini has been discussed here and there for a few years now, always with the promise that it will open doors we have never had. Want to make a new way to do layout? Houdini. Want to create a new kind of gradient? Houdini.
We have reached the point where this is more than just an idea or a spec. There are modules now in Blink browsers behind a flag (as of this writing, this is the only way to try it). There are many code examples, but at first glance it all seems… complicated. Some of the key examples that resources point to look like a mysterious combination of CSS Variables, Canvas drawing, and JS in CSS.
CSS.registerProperty(). We will look at Houdini in the context of CSS Custom Properties (CSS Variables) and animation.
Setting the Stage: An Intro to Custom Properties
I saw the power of Custom Properties with their support independent transform properties in Firefox, Edge, Chrome, Opera, and Safari. They allows us, for example, to modify a
scale without modifying an existing
rotate on the same element, even though those are tied into a single
Custom Properties are powerful since they introduced a variable option to CSS natively for the first time, and they fit in with the cascade and inheritance nicely. But they, by design for the first spec, are not as powerful as they can be. To get the initial implementations in so many browsers semi-quickly, their power was limited. When you say
--my-prop: 2px, the browser does not really know that is a length value. When it is used in the context of another property that expects a length (e.g.
transform: translateX(var(--my-prop))), the browser then is able to parse it and treat it like a length.
Therefore, you cannot set a
--my-prop or modify its value in a
@keyframes rule and have it animate smoothly. The browser does not have enough information to know what kind of syntax it is dealing with, or if it is even animatable. You can, however, still transition the property that it is used within if it is animatable (like the
CSS.registerProperty() from the Properties and Values API
With the Properties and Values API spec (inside the larger Houdini endeavor) we can now tell the browser what to expect for each property.
Here we can say that we want our CSS custom property named
--my-prop to always have a valid
<length> value. We also specify an initial value (for when no value is defined when we reference it via
var()) and whether it inherits or not. To show the flexibility
inherits provides, take the following CSS:
true then the width of the list item will be
20em since it can inherit its value from an ancestor. Otherwise, a
false value will mean the list items will have a width of
By defining rules around how this property will behave we can have the browser reject syntaxes we do not want to support. Even more exciting (to me) is that we now have told the browser that a property is a
length syntax (or angle, number, color, etc. as defined in the spec) which the browser knows how to animate.
Fancy Transforms as an example
transform that is composed of the the same custom properties in different variations of rotations. We can give them all the exact same
@keyframes, but each will have a different animation since the custom properties combine into different
This extends to transitions, as well where you can specify different transitions for each of the transform functions that make up a single
But why stop there when you can even combine animations and transitions on a single
transform. In this example, each element still has a
keyframe animation, but on
body:hover the middle element will do an additional rotation around the Z axis, smoothly performing its
transition while the
animation continues. The browser has all the informaiton it needs to interpolate the values thanks to the custom property’s syntax defined with
Vincent De Oliveira has an excellent playground that shows off Houdini at a larger scale, including the other APIs under the Houdini banner like Paint and Layout. Google also is putting the initial Paint API in Chrome stable soon, with a solid introduction by Surma.