Yoga Layout Engine
website·Indexed 35 days ago
https://yogalayout.devAn embeddable layout system used by UI frameworks like React Native. Yoga implements the CSS Flexible Box Model, providing a cross-platform layout engine with support for flexbox, absolute positioning, and incremental layout. Documentation covers styling properties such as flex-direction, gap, and aspect-ratio, as well as version updates including Yoga 3.0, 3.1, and 3.2.
What's inside Yoga
- Yoga is now distributed as an ES Module using top-level await to load WebAssembly. This replaces the previous complex matrix of asm.js/wasm and sync/async binaries. It provides a single binary that presents a synchronous-looking API across different environments and bundlers, with the underlying binary distributed as a base64 encoded JavaScript blob.
Understand Yoga layout system capabilities
Yoga is an embeddable layout system designed to determine the size and position of boxes. It is not a UI framework and does not perform any drawing or rendering. It implements a subset of CSS, primarily focusing on Flexbox, to provide a consistent layout model across native platforms and web browsers. Yoga is written in C++ and exposes a public C API, making it compatible with various languages through official and unofficial bindings.Delegate leaf node sizing using Yoga Measure Functions
Yoga allows leaf nodes to delegate sizing to an external layout system via Measure Functions. This is used when content size depends on factors not expressible within Yoga, such as text or views rendered by a different system. A measure function callback is set on a node, and Yoga invokes it when the node lacks a definite dimension to determine the required size based on available space.Migrate absolute positioning to Yoga 3.2
Yoga 3.2 removes the legacy absolute positioning path and theAbsolutePositioningIncorrecterratum. To preserve compatibility with existing code that relied on the previous incorrect behavior (specifically omitting padding when a position was not specified on an absolute node), use the new erratum:AbsolutePositionWithoutInsetsExcludesPadding.Install Yoga 2.0
Yoga 2.0 is available via npm, Maven Central, and CocoaPods.// npm (package.json) "dependencies": { "yoga-layout": "^2.0.0" }// Gradle (build.gradle) dependencies { implementation("com.facebook.yoga:yoga:2.0.0") }# CocoaPods (Podfile) pod 'Yoga', '~> 2.0.0'Initialize Yoga in JavaScript/TypeScript
Theyoga-layoutpackage now requires asynchronous loading for WebAssembly binaries in browsers and Node.js. UseloadYoga()to initialize the engine before creating nodes.import {loadYoga, Align} from 'yoga-layout'; const Yoga = await loadYoga(); const node = Yoga.Node.create(); node.setAlignContent(Align.Center);Optimize UI updates using Yoga incremental layout
Yoga supports incremental layout to avoid recalculating the entire tree when only small portions of the UI change. Yoga automatically marks a node and its ancestors as 'dirty' if the node's style or children are modified. During subsequent layout passes, Yoga skips nodes that are not dirty, provided their parent constraints remain unchanged.
To optimize the process of applying layout results to the actual UI, developers can use the
HasNewLayoutflag. This allows the application to skip traversing subtrees where no layout updates occurred.void applyLayout(YGNodeRef node) { // Check if this node or its children have changed if (!YGNodeHasNewLayout(node)) { return; } // Reset the flag so we don't process it again next time YGNodeSetHasNewLayout(node, false); // Perform the actual UI update work here // ... // Recursively apply layout to children for (size_t i = 0; i < YGNodeGetChildCount(node); i++) { applyLayout(YGNodeGetChild(node, i)); } }Offset nodes using insets in Yoga Layout
Insets allow you to offset a node from its original position or its containing block. The behavior of insets depends on the node's
positiontype:- Static: Insets have no effect.
- Relative: Insets move the node relative to where it would normally be placed in the container. For example, setting a right edge inset of 10 units offsets the node so its right edge is 10 units away from its original position.
- Absolute: Insets move the node relative to its containing block. For example, setting a right edge inset of 10 units offsets the node so its right edge is 10 units away from the containing block's right edge.
Constraint Note: If a node has a fixed size and opposite insets are defined (e.g., both left and right), the left and top edges take priority.
// C/C++ API example to set an inset YGNodeStyleSetPosition(node, edge, position);// JavaScript/React-style example <Layout config={{useWebDefaults: false}}> <Node style={{ width: 200, height: 200 }}> <Node style={{ height: 50, width: 50, top: 50, left: 50, }} /> </Node> </Layout>C++ Toolchain and Infrastructure Requirements
Yoga now targets a subset of C++ 20. The following toolchains are supported:
- MSVC 2019+
- Clang/libc++ 14+
- GCC/libstdc++ 11+
- Android NDK 26+
- XCode 14.3+
Additionally, the reference Android build and artifacts now target Android SDK 34.
Build and style a Yoga node tree
In Yoga, every layout box is represented as a Yoga Node. These nodes are organized into a tree structure to store input styles and output layout results. Nodes are created, styled (e.g., setting flex direction, width, height, and margins), and linked as parent-child relationships usingYGNodeInsertChild.#include <yoga/Yoga.h> // Create root node and set styles YGNodeRef root = YGNodeNew(); YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); YGNodeStyleSetWidth(root, 100.0f); YGNodeStyleSetHeight(root, 100.0f); // Create and add first child YGNodeRef child0 = YGNodeNew(); YGNodeStyleSetFlexGrow(child0, 1.0f); YGNodeStyleSetMargin(child0, YGEdgeRight, 10.0f); YGNodeInsertChild(root, child0, 0.0f); // Create and add second child YGNodeRef child1 = YGNodeNew(); YGNodeStyleSetFlexGrow(child1, 1.0f); YGNodeInsertChild(root, child1, 1.0f);Integrate Yoga C++ APIs
Yoga has strengthened the boundary between public APIs and internal C++ implementation. Every top-level header is now a public API and is compatible with C, C++, Objective C, and Swift. Integrators should note that increased const-correctness in the public API may require mechanical changes to measure functions.Install Yoga 3.0 via package managers
Yoga 3.0 is available across multiple package managers for JavaScript, Android, iOS (CocoaPods), and SwiftPM.// JavaScript (package.json) { "dependencies": { "yoga-layout": "^3.0.0" } }// Android (build.gradle.kts) dependencies { implementation("com.facebook.yoga:yoga:3.0.0") }# CocoaPods (Podfile) pod 'Yoga', '~> 3.0.0'// SwiftPM (Package.swift) import PackageDescription let package = Package( dependencies: [ .package(url: "https://github.com/facebook/yoga.git", from: "3.0.0") ], )