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.
In short, Houdini gives a developer building blocks in JavaScript to allow writing new kinds of CSS.
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.
Luckily, there is a way to start exploring Houdini with one basic JavaScript method, called CSS.registerProperty()
. We will look at Houdini in the context of CSS Custom Properties (CSS Variables) and animation.
See the Pen Dance of the Houdini Hexagons by Dan Wilson (@danwilson) on CodePen.
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 transform
property.
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 transition
for --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 transform
earlier).
Enter 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.
if (window.CSS && CSS.registerProperty) {
CSS.registerProperty({
name: '--my-prop',
syntax: '<length>',
initialValue: '0px',
inherits: false
});
}
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:
ul, ol {
--my-prop: 20em;
}
li {
width: var(--my-prop);
}
If inherits
is 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 0px
since that was the initial value defined in our JavaScript and there is no other value defined specifically on the li
element.
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
See the Pen Animating CSS Variables (Houdini Basics) by Dan Wilson (@danwilson) on CodePen.
We register several properties in the JavaScript as angles, and then we give three nested elements each a 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 transform
s.
This extends to transitions, as well where you can specify different transitions for each of the transform functions that make up a single transform
property.
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 CSS.registerProperty()
.
See the Pen Animating CSS Variables (Houdini Basics 2) by Dan Wilson (@danwilson) on CodePen.
More Info
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.
Enjoy.