Yoga Layout Engine

website·Indexed 35 days ago

https://yogalayout.dev

An 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.

Tokens
9.8K
Snippets
45
Records
76
Agent score
72%

What's inside Yoga

  1. Use Yoga as an ES Module

    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.
  2. 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.
  3. 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.
  4. Migrate absolute positioning to Yoga 3.2

    Yoga 3.2 removes the legacy absolute positioning path and the AbsolutePositioningIncorrect erratum. 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.
  5. 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'
  6. Initialize Yoga in JavaScript/TypeScript

    The yoga-layout package now requires asynchronous loading for WebAssembly binaries in browsers and Node.js. Use loadYoga() 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);
  7. 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 HasNewLayout flag. 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));
      }
    }
  8. 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 position type:

    • 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>
  9. 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.

  10. 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 using YGNodeInsertChild.
    #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);
  11. 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.
  12. 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")
        ],
    )