Houdini

May 20, 2023

Houdini is a collection of low-level APIs that developers can use to extend the capabilities of the browser’s rendering engine. It is designed to enable developers to create their own CSS properties and JavaScript functions, which can be used to create new visual effects or animations that were previously not possible with CSS alone.

Purpose

Houdini was created to solve a fundamental problem with CSS: it was not designed to be extensible. CSS is a declarative language that describes the presentation of HTML documents. However, it has many limitations in terms of what it can do. For example, CSS can only animate certain properties, and it has no way of accessing the DOM or interacting with JavaScript.

Houdini was created to address these limitations. It allows developers to create their own CSS properties and JavaScript functions, which can be used to define new visual effects or animations. This makes it possible to create more complex and dynamic user interfaces, and to achieve effects that were previously only possible with JavaScript or WebGL.

Usage

Houdini consists of several different APIs that can be used together or separately, depending on the needs of the developer. These APIs include the following:

Paint API

The Paint API allows developers to create custom CSS properties that define how an element should be painted. This can include custom gradients, patterns, and images.

For example, suppose you want to create a custom gradient that changes color based on the position of the mouse. With the Paint API, you can define a custom CSS property that takes the position of the mouse as a parameter, and returns a gradient with the appropriate colors.

.my-element {
  background-image: paint(my-paint, 0 0);
}

@custom-selector :--my-element .my-element;
@custom-media --my-media (width: 500px);

@viewport {
  min-width: 300px;
  max-width: 800px;
}

@keyframes my-animation {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}

@counter-style my-counter {
  system: fixed;
  symbols: 'A' 'B' 'C' 'D' 'E';
  suffix: ' ';
}

@font-face {
  font-family: 'My Font';
  src: url('myfont.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
}

@media (max-width: 600px) {
  .my-element {
    background-image: paint(my-paint, 0 0);
  }
}

Layout API

The Layout API allows developers to create their own layout algorithms that can be used in conjunction with CSS. This can include custom grid systems, flexbox implementations, or specialized layout algorithms for particular types of content.

For example, suppose you want to create a custom layout algorithm for a card-based UI. With the Layout API, you can define a special CSS property that takes the number of cards and their dimensions as parameters, and returns the appropriate layout.

.card-container {
  display: layout(mycardlayout, 3, 200px, 300px);
}

Animation and Transition API

The Animation and Transition API allows developers to create custom animations and transitions that can be applied to CSS properties. This can include custom easing functions, keyframe-based animations, and more complex animations that combine multiple CSS properties.

For example, suppose you want to create a custom animation that combines a scale transform and a color change. With the Animation and Transition API, you can define a custom CSS property that takes the target scale and color as parameters, and returns a keyframe-based animation that combines the two.

.my-element {
  animation: my-animation 2s ease-in-out;
}

@keyframes my-animation {
  from {
    transform: scale(1);
    color: white;
  }
  to {
    transform: scale(2);
    color: red;
  }
}

Parser API

The Parser API allows developers to create their own CSS parsers that can be used to parse custom CSS properties. This can include custom syntax for defining new properties or functions, or specialized parsers for particular types of content.

For example, suppose you want to create a custom syntax for defining color gradients. With the Parser API, you can define a custom CSS property that takes a list of color values and positions, and returns a gradient with the appropriate colors.

.my-element {
  background-image: my-gradient(red 0%, green 50%, blue 100%);
}

Font Metrics API

The Font Metrics API allows developers to access metrics information about fonts, such as glyph dimensions and kerning pairs. This can be useful for creating custom typography effects or layout algorithms that depend on font metrics.

For example, suppose you want to create a custom layout algorithm for a text editor that takes into account the dimensions of individual glyphs. With the Font Metrics API, you can access the necessary metrics information and use it to calculate the appropriate layout.

@font-face {
  font-family: 'My Font';
  src: url('myfont.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
}

.my-element {
  font-family: 'My Font';
  font-size: 16px;
}

/* Get the dimensions of the letter 'A' */
var font = new FontFace('My Font', 'url(myfont.woff2)');
font.load().then(function() {
  var metrics = font.getFontMetrics();
  var width = metrics.glyphs.A.width;
  var height = metrics.glyphs.A.height;
});