Lesson 33 - Layout engine
Browsers implement several layout systems, such as Flexbox, Grid, and Block, making it easy to achieve effects like “centering” without manually calculating node positions.
For infinite canvas-like applications operating outside the DOM, you must implement your own layout engine logic. Figma has implemented Auto Layout, where Grid is currently in beta, while Vertical and Horizontal correspond to CSS's flex-direction property. For details, see: Figma - Guide to auto layout

In this lesson, we will implement Flexbox layouts and support CSS properties with the same names on nodes:
const parent = {
id: 'parent',
type: 'rect',
x: 100,
y: 10,
width: 100,
height: 100,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
};
const child = {
id: 'child',
parentId: 'parent',
type: 'rect',
width: '50%',
height: '50%',
};Yoga
Using the Yoga layout engine in the frontend is only possible via WASM. Currently, there are several available implementations:
- yoga-layout-prebuilt It's been a long time since the last update.
- yoga-wasm-web Early satori used it to convert HTML into SVG and compute layouts. taffy also has related example
- yoga-layout We recommend using it, and our implementation is also based on it. react-pdf/yoga also use it.
It is worth noting that Yoga also applies to 3D space, provided that a plane is specified. For details, see:react-three-flex
Another important difference with DOM Flexbox is that you have to specify the plane of the container in 3D. The elements will be positioned in the 2D plane given by the two axes, using width and height calculated along the two axes.

pixijs/layout
pixijs/layout is also implemented using Yoga. Similar implementations include: pixi-flex-layout
const container = new Container({layout: {
width: '80%',
height: '80%',
gap: 4,
flexWrap: 'wrap',
justifyContent: 'center',
alignContent: 'center',
}});troika-flex-layout
troika-flex-layout, computed in a WebWorker using yoga-layout-prebuilt:
import { requestFlexLayout } from 'troika-flex-layout'
// Describe your layout style tree, with a unique id for each node:
const styleTree = {
id: 'root',
width: 100,
height: 100,
alignItems: 'center',
justifyContent: 'center',
children: [
{
id: 'child',
width: '50%',
height: '50%'
}
]
}
// Initiate a layout request with a callback function:
requestFlexLayout(styleTree, results => {
// The results are a mapping of node ids to layout boxes:
// {
// root: { left: 0, top: 0, width: 100, height: 100 },
// child: { left: 25, top: 25, width: 50, height: 50 }
// }
})Alternatives to Yoga
Pure JS implementations:
- Motion Canvas Layouts Native browser-based Flexbox implementation, eliminating the need to reimplement complex layout algorithms
- Simplifying WebGL: Building an Effective Layout Engine
Rust implementations:
- stretch implements Flexbox and provides a
stretch-layoutWASM binding, but it has not been maintained for a long time. - taffy A high-performance UI layout library written in Rust, currently implementing several CSS layout algorithms including Flexbox, Grid, and Block. However, WASM bindings are not yet available. For details, see: taffy wasm bindings
[WIP] Our implementation
A layout tree parallel to the scene graph needs to be constructed.