Escape the box with Houdini

CSS is a powerful technology for styling web content, with one significant drawback (no not specificity). We’re restricted to the styling primitives built into the language (and browser), which relies on others to specify and implement them, and can take years.

Well, until now. Enter Houdini.

Houdini is a set of lower level APIs that allow us to essentially create our own visual style, layout, and animation properties for CSS. Sounds like magic? That’s why it’s called Houdini.

In this presentation creative developer Ruth John will show us how the illusion is created.

Escape the box with Houdini

Ruth John, Creative Developer

Note Ruth will tweet the resources – follow @rumyra

Ruth wrote documentation about CSS Houdini for MDN docs and this intro to Houdini comes from that experience.

Houdini is a suite of APIs to help developers have better to access to CSS through JavaScript. They are designed to solve the problem of features being unavailable for quite a long time.

What’s under the Houdini banner?

  • Typed OM
  • CSS Pain API
  • Properties & Values
  • Layout API
  • Animation Worklet

Ruth will be focusing on the first three partly due to time constraints, but also as they are closer to workable browser support.

Typed OM underpins a lot of the other APIs. It’s access to CSS values as types in JavaScript. A quick syntax refresh to set the scene:

button {
  border-width-top: 4px;
}
  • button is the selector
  • border-width-top is the property
  • 4px is the value

Typed OM gives access to the value, the 4px.

To access CSS values at the moment we need to use fairly cumbersom syntax including getComputedStyle which returns values as a string. So then you have to process the string to work out the value separately from the unit and so on. Then we have to put it all back together again to set the new style as a string.

Wouldn’t it be better if we could get style as an object splitting the value and unit? element.computedStyleMap().get('property') lets you do that. So you get { value: 4, unit: "px"} instead of a string. Then you can manipulate and set the value as a number instead of a string.

Value types include…

  • CSSStyleValue – not used by itself much, it is the subclass behind the others
  • CSSNumericValue
  • CSSUnitValue
  • CSSMathSum – if you use calc/min/etc it will come back as a CSSMathSum
  • CSSTransformValue – rotations, skews, etc
  • CSSKeywordValue – values that are unquoted words like auto
  • CSSUnparsedValue – unknowable values like custom properties
  • CSSImageValue – a loose type as there are so many kinds of images

…and there are more to come. The idea is to have a different type for every value we have in CSS.

So how can we create one of these values?

new CSSUnitValue(10, px)

or

CSS.px(10)

Both create { value: 10, unit: "px" }

attributeStyleMap methods:

element.attributeStyleMap().set('border-top-width’, CSS.px(10))

element.attributeStyleMap().has('border-top-width’)

element.attributeStyleMap().delete('border-top-width’)

element.attributeStyleMap().clear()

element.attributeStyleMap().get('border-top-width’)

There are also numeric methods for working on numeric types. You can add, subtract and find values; you can convert them using to; and test with equals.

So that’s Typed OM and it may seem like quite a lot when we can already manipulate style with JS, but it underpins everything else.

Properties & Values – we’ve probably all seen CSS variables by now; and we can use setProperty to manipulate them from JS.

This also means we can use JS to do things like generate our own custom gradient, then make it available using CSS.registerProperty – this is linked back to the type set in Typed OM.

Reference: Ana Tudo’s codepen

Workers are JS scripts that run off the main thread – ie. in the background. It communicates with the main thread using messages.

Worklets are the same, but with a predefined class and access to predefined properties specified in its API.

This set us up to understand the CSS Paint API, which lets us register a paint worklet wherever we might want to use an image in our CSS. We already have that; but a worklet opens up opportunities to handle things like resizing images.

It works like this:

.slide {
  background-image: paint(dots)
}
CSS.paintWorklet.addModule('dots.js’)

Inside dots.js you can then write code to create the image with HTML5 canvas.

Reference: Jeremy Wagner’s paintlets project

To finish up, a quick look at Layout and Animation – they basically work the same way as Paint but letting you manipulate layout and animation. The key concept is that you can access worklets in your CSS; and those worklets have access to the element.

Please check these things out and give feedback to the W3C about what you want to see in them.

@rumyra