loading...
Cover image for CSS Houdini's Layout API explained

CSS Houdini's Layout API explained

adrianbdesigns profile image Adrian Bece Originally published at smashingmagazine.com ・4 min read

This post has been originally published on Smashing Magazine and I decided to split it into parts to make it more digestible. I'll be converting the post into markdown and publish a part of it on DEV every week. If you want to read it right away in its entirety, feel free to read it on Smashing Magazine until all parts are available on DEV. Thank you.


Layout API

The Layout API allows developers to extend the browser’s layout rendering process by defining new layout modes that can be used in display CSS property. Layout API introduces new concepts, is very complex and offers a lot of options for developing custom layout algorithms.

Similarly to other Worklets, the layout Worklet needs to be registered and defined first.

registerLayout('exampleLayout', class {
  static get inputProperties() { return ['--exampleVariable']; }

  static get childrenInputProperties() { return ['--exampleChildVariable']; }

  static get layoutOptions() {
    return {
      childDisplay: 'normal',
      sizing: 'block-like'
    };
  }

  intrinsicSizes(children, edges, styleMap) {
    /* ... */
  }

  layout(children, edges, constraints, styleMap, breakToken) {
    /* ... */
  }
});

Worklet register contains the following methods:

  • inputProperties: An array of CSS custom properties that the Worklet will keep track of that belongs to a Parent Layout element, i.e. the element that calls this layout. This array represents dependencies of a Layout Worklet.
  • childrenInputProperties: An array of CSS custom properties that the Worklet will keep track of that belong to child elements of a Parent Layout element, i.e. the children of the elements that set this layout.
  • layoutOptions: defines the following layout properties:
    • childDisplay: can have a pre-defined value of block or normal. Determines if the boxes will be displayed as blocks or inline.
    • sizing: can have a pre-defined value of block-like or manual. It tells the browser to either pre-calculate the size or not to pre-calculate (unless a size is explicitly set), respectively.
  • intrinsicSizes: defines how a box or its content fits into a layout context.
    • children: child elements of a Parent Layout element, i.e. the children of the element that call this layout.
    • edges: Layout Edges of a box
    • styleMap: typed OM styles of a box
  • layout: the main function that performs a layout.
    • children: child elements of a Parent Layout element, i.e. the children of the element that call this layout.
    • edges: Layout Edges of a box
    • constraints: constraints of a Parent Layout
    • styleMap: typed OM styles of a box
    • breakToken: break token used to resume a layout in case of pagination or printing.

Like in the case of a Paint API, the browser rendering engine determines when the paint Worklet is being called. It only needs to be added to an HTML or main JavaScript file.

CSS.layoutWorklet.addModule('path/to/worklet/file.js');

And, finally, it needs to be referenced in a CSS file

.exampleElement {
  display: layout(exampleLayout);
}

How Layout API Performs Layout

In the previous example, exampleLayout has been defined using the Layout API.

.exampleElement {
  display: layout(exampleLayout);
}

This element is called a Parent Layout that is enclosed with Layout Edges which consists of paddings, borders and scroll bars. Parent Layout consists of child elements which are called Current Layouts. Current Layouts are the actual target elements whose layout can be customized using the Layout API. For example, when using display: flex; on an element, its children are being repositioned to form the flex layout. This is similar to what is being done with the Layout API.

Each Current Layout consists of Child Layout which is a layout algorithm for the LayoutChild (element, ::before and ::after pseudo-elements) and LayoutChild is a CSS generated box that only contains style data (no layout data). LayoutChild elements are automatically created by browser rendering engine on style step. Layout Child can generate a Fragment which actually performs layout render actions.

Example

Similarly to the Paint API example, this example is importing a masonry layout Worklet directly from Google Chrome Labs repository, but in this example, it’s used with image content instead of text. Complete source code is available on the example repository.

Masonry layout example

Masonry layout example (uses Masonry Worklet by Google Chrome Labs

Feature Detection

if (CSS.layoutWorklet) {
  /* ... */
}

W3C Specification Status

Browser Support

Google Chrome Microsoft Edge Opera Browser Firefox Safari
Partial support (*) Partial support (*) Partial support (*) Not supported Not supported

* supported with “Experimental Web Platform features” flag enabled.

Data source: Is Houdini Ready Yet?


These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.

Buy Me A Coffee

Thank you for taking the time to read this post. Keep an eye out for the next part in the series. If you've found this useful, please give it a ❤️ or 🦄, share and comment.

Posted on by:

adrianbdesigns profile

Adrian Bece

@adrianbdesigns

React, Frontend, Magento 2 certified developer. Magento PWA Studio contributor. Rock and metal music fan. Reads Dune, sci-fi novels and Calvin & Hobbes. Creates amazing interfaces @ prototyp.digital

Discussion

markdown guide