# CSS Layout API Level 1

## Editor’s Draft, 1 January 1970

This version:
  https://drafts.css-houdini.org/css-layout-api-1/
Latest published version:
  https://www.w3.org/TR/css-layout-api-1/
Feedback:
  public-houdini@w3.org with subject line “`[css-layout-api] … message topic …`” (archives)
Editors:
  Greg Whitworth
  Ian Kilpatrick
  Tab Atkins-Bittner (Google)
  Robert O'Callahan
  Rossen Atanassov
Former Editor:
  Shane Stephens
Issue Tracking:
  GitHub Issues

Copyright © 1970 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.

## Abstract

An API for allowing web developers to define their own layout modes with javascript. See EXPLAINER.

## Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

GitHub Issues are preferred for discussion of this specification. When filing an issue, please put the text “css-layout-api” in the title, preferably like this: “[css-layout-api] …summary of comment…”. All issues and comments are archived.

This document was produced by the CSS Working Group.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 March 2019 W3C Process Document.

## 1. Introduction

This section is not normative.

The layout stage of CSS is responsible for generating and positioning fragments from the box tree.

This specification describes an API which allows developers to layout a box in response to computed style and box tree changes.

For a high level overview of this API, see the EXPLAINER.

## 2. Layout API Containers

A new alternative value is added to the <display-inside> production: `layout(<ident>)`.

layout()
  This value causes an element to generate a layout API container box.

A layout API container is the box generated by an element with a <display-inside> computed value layout().

A layout API container establishes a new layout API formatting context for its contents. This is the same as establishing a block formatting context, except that the layout provided by the author is used instead of the block layout. For example, floats do not intrude into the layout API container, and the layout API container’s margins do not collapse with the margins of its contents.

Layout API containers form a containing block for their contents exactly like block containers do. [CSS21]

Note: In a future level of the specification there may be a way to override the containing block behaviour.

The overflow property applies to layout API containers. This is discussed in § 5.3 Overflow.

As the layout is entirely up to the author, properties which are used in other layout modes (e.g. flex, block) may not apply. For example an author may not respect the margin property on children.

The HTML below shows an example of setting the display to a layout() function, if the CSS Layout API is supported.

    <!DOCTYPE html>
    <style>
    @supports (display: layout(centering)) {
      .centering-layout { display: layout(centering); }
    }
    </style>
    <div class="centering-layout"></div>

### 2.1. Layout API Container Painting

Layout API Container children paint exactly the same as inline blocks [CSS21], except that the order in which they are returned from the layout method (via `childFragments`) is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.

### 2.2. Box Tree Transformations

The inflow children of a layout API container can act in different ways depending on the value of layout options' `childDisplay` (set by `layoutOptions` on the class).

If the value of layout options' `childDisplay` is `"block"` the display value of that child is blockified. This is similar to children of flex containers or grid containers. See [css3-display].

If the value of layout options' `childDisplay` is `"normal"`, no blockification occurs. Instead children with a <display-outside> computed value of inline (a root inline box) will produce a single `LayoutFragment` representing each line when `layoutNextFragment()` is called.

Note: This allows authors to adjust the available inline size of each line, and position each line separately.

Children of a `LayoutChild` which represents root inline box also have some additional transformations.

- A block-level box inside a inline-level box is inlinified I.e. its <display-outside> is set to inline.

- A float inside a inline-level box is not taken out of flow. Instead it must be treated as inflow, and be inlinified.

In both of the above cases the children become atomic inlines.

Note: User agents would not perform any "inline splitting" or fragmenting when they encounter a block-level box.

Note: In the example below "inline-span" would be represented as a single `LayoutChild` with both "block" and "float" being atomic inlines.

    <span id="inline-span">
      Text
      <div id="block"></div>
      <div id="float"></div>
      Text
    </span>

## 3. Layout Worklet

The `layoutWorklet` attribute allows access to the `Worklet` responsible for all the classes which are related to layout.

The `layoutWorklet`'s worklet global scope type is `LayoutWorkletGlobalScope`.

    partial namespace CSS {
        [SameObject] readonly attribute Worklet layoutWorklet;
    };

The `LayoutWorkletGlobalScope` is the global execution context of the `layoutWorklet`.

    [Global=(Worklet,LayoutWorklet),Exposed=LayoutWorklet]
    interface LayoutWorkletGlobalScope : WorkletGlobalScope {
        void registerLayout(DOMString name, VoidFunction layoutCtor);
    };

Web developers can feature detect by:

    if ('layoutWorklet' in CSS) {
      console.log('CSS Layout API available!');
    }

### 3.1. Concepts

This section describes internal data-structures created when `registerLayout(name, layoutCtor)` is called.

A layout definition is a struct which describes the information needed by the `LayoutWorkletGlobalScope` about the author defined layout (which can be referenced by the layout() function). It consists of:

- class constructor which is the class constructor.

- layout function which is the layout function callback.

- intrinsic sizes function which is the intrinsic sizes function callback.

- constructor valid flag.

- input properties which is a list of `DOMStrings`.

- child input properties which is a list of `DOMStrings`.

- layout options a `LayoutOptions`.

A document layout definition is a struct which describes the information needed by the document about the author defined layout (which can be referenced by the layout() function). It consists of:

- input properties which is a list of `DOMStrings`

- child input properties which is a list of `DOMStrings`.

- layout options a `LayoutOptions`.

### 3.2. Registering A Layout

The section describes how a web developer uses `registerLayout(name, layoutCtor)` to register a layout.

    [Exposed=LayoutWorklet]
    dictionary LayoutOptions {
      ChildDisplayType childDisplay = "block";
      LayoutSizingMode sizing = "block-like";
    };

    [Exposed=LayoutWorklet]
    enum ChildDisplayType {
        "block", // default - "blockifies" the child boxes.
        "normal",
    };

    [Exposed=LayoutWorklet]
    enum LayoutSizingMode {
        "block-like", // default - Sizing behaves like block containers.
        "manual", // Sizing is specified by the web developer.
    };

The document has a map of document layout definitions. Initially this map is empty; it is populated when `registerLayout(name, layoutCtor)` is called.

The `LayoutWorkletGlobalScope` has a map of layout definitions. Initially this map is empty; it is populated when `registerLayout(name, layoutCtor)` is called.

Each box representing a layout API container has a map of layout class instances. Initially this map is empty; it is populated when the user agent calls either determine the intrinsic sizes or generate a fragment for a box.

Each box representing a layout API container has a styleMap internal slot. This is a `StylePropertyMapReadOnly` which contains the properties listed in `inputProperties`.

The user agent clear the styleMap internal slot for a box when:

- The computed values of input properties for the box changes.

- When the box is removed from the box tree.

- Every 1000 layout passes.

  Note: The above rule exists to ensure that web developers do not rely on being able to store non-regeneratable state on the `StylePropertyMapReadOnly` object. The 1000 limit was picked as a high upper bound, this limit may improve (downwards) over time.

Note: The shape of the class should be:

    registerLayout('example', class {
        static inputProperties = ['--foo'];
        static childrenInputProperties = ['--bar'];
        static layoutOptions = {
          childDisplay: 'normal',
          sizing: 'block-like'
        };

        async intrinsicSizes(children, edges, styleMap) {
            // Intrinsic sizes code goes here.
        }

        async layout(children, edges, constraints, styleMap, breakToken) {
            // Layout code goes here.
        }
    });

The algorithm below is run when the `registerLayout(name, layoutCtor)` is called. It notifies the user agent layout engine about the new user defined layout.

When the `registerLayout(name, layoutCtor)` method is called, the user agent must run the following steps:

1. If the name is an empty string, throw a TypeError and abort all these steps.

2. Let layoutDefinitionMap be `LayoutWorkletGlobalScope`'s layout definitions map.

3. If layoutDefinitionMap[name] exists throw a "`InvalidModificationError`" `DOMException` and abort all these steps.

4. Let inputProperties be an empty `sequence<DOMString>`.

5. Let inputPropertiesIterable be the result of Get(layoutCtor, "inputProperties").

6. If inputPropertiesIterable is not undefined, then set inputProperties to the result of converting inputPropertiesIterable to a `sequence<DOMString>`. If an exception is thrown, rethrow the exception and abort all these steps.

7. Filter inputProperties so that it only contains supported CSS properties and custom properties.

   Note: The list of CSS properties provided by the input properties getter can either be custom or native CSS properties.

   Note: The list of CSS properties may contain shorthands.

   Note: In order for a layout class to be forwards compatible, the list of CSS properties can also contains currently invalid properties for the user agent. For example `margin-bikeshed-property`.

8. Let childInputProperties be an empty `sequence<DOMString>`.

9. Let childInputPropertiesIterable be the result of Get(layoutCtor, "childInputProperties").

10. If childInputPropertiesIterable is not undefined, then set childInputProperties to the result of converting childInputPropertiesIterable to a `sequence<DOMString>`. If an exception is thrown, rethrow the exception and abort all these steps.

11. Filter childInputProperties so that it only contains supported CSS properties and custom properties.

12. Let layoutOptionsValue be the result of Get(layoutCtor, "layoutOptions").

13. Let layoutOptions be the result of converting layoutOptionsValue to a `LayoutOptions`. If an exception is thrown, rethrow the exception and abort all these steps.

14. Let prototype be the result of Get(layoutCtor, "prototype").

15. If the result of Type(prototype) is not Object, throw a TypeError and abort all these steps.

16. Let intrinsicSizesValue be the result of Get(prototype, "intrinsicSizes").

17. Let intrinsicSizes be the result of converting intrinsicSizesValue to the Function callback function type. Rethrow any exceptions from the conversion.

18. Let layoutValue be the result of Get(prototype, `"layout"`).

19. Let layout be the result of converting layoutValue to the Function callback function type. Rethrow any exceptions from the conversion.

20. Let definition be a new layout definition with:

    - class constructor being layoutCtor.

    - layout function being layout.

    - intrinsic sizes function being intrinsicSizes.

    - constructor valid flag being true.

    - child input properties being childInputProperties.

    - input properties being inputProperties.

    - layout options being layoutOptions.

21. Set layoutDefinitionMap[name] to definition.

22. Queue a task to run the following steps:

    1. Let documentLayoutDefinitionMap be the associated document’s document layout definitions map.

    2. Let documentDefinition be a new document layout definition with:

       - child input properties being childInputProperties.

       - input properties being inputProperties.

       - layout options being layoutOptions.

    3. If documentLayoutDefinitionMap[name] exists, run the following steps:

       1. Let existingDocumentDefinition be the result of get documentLayoutDefinitionMap[name].

       2. If existingDocumentDefinition is `"invalid"`, abort all these steps.

       3. If existingDocumentDefinition and documentDefinition are not equivalent, (that is input properties, child input properties, and layout options are different), then:

          Set documentLayoutDefinitionMap[name] to `"invalid"`.

          Log an error to the debugging console stating that the same class was registered with different `inputProperties`, `childInputProperties`, or `layoutOptions`.

    4. Otherwise, set documentLayoutDefinitionMap[name] to documentDefinition.

### 3.3. Terminology

We define the following terms to be clear about which layout algorithm (formatting context) we are talking about.

The current layout is the layout algorithm for the box we are currently performing layout for.

The parent layout is the layout algorithm for the box’s direct parent, (the layout algorithm which is requesting the current layout to be performed).

A child layout is the layout algorithm for a `LayoutChild` of the current layout.

## 4. Layout API

This section describes the objects of the Layout API provided to web developers.

### 4.1. Layout Children

A `LayoutChild` represents a inflow CSS generated box before layout has occurred. (The box or boxes will all have a computed value of display that is not none).

The `LayoutChild` does not contain any layout information itself (like inline or block size) but can be used to generate `LayoutFragment`s which do contain layout information.

An author cannot construct a `LayoutChild` with this API, this happens at a separate stage of the user agent rendering engine (post style resolution).

An array of `LayoutChild`ren is passed into the layout/intrinsicSizes methods which represents the children of the current box which is being laid out.

    [Exposed=LayoutWorklet]
    interface LayoutChild {
        readonly attribute StylePropertyMapReadOnly styleMap;

        Promise<IntrinsicSizes> intrinsicSizes();
        Promise<LayoutFragment> layoutNextFragment(LayoutConstraintsOptions constraints, ChildBreakToken breakToken);
    };

The `LayoutChild` has internal slot(s):

- `[[box]]` a CSS box.

- `[[styleMap]]` a `StylePropertyMapReadOnly`, this is the computed style for the child, it is populated with only the properties listed in `childInputProperties`.

- `[[unique id]]` the unique id of the current layout api context. This slot is used so that a `LayoutChild` used outside the current layout pass is invalid.

The `[[styleMap]]` may be pre-populated when the computed value for properties listed in the in child input properties for the `[[box]]`.

The example below shows the basic usage of a `LayoutChild`.

    registerLayout('example-layout-child', class {
      static childInputProperties = ['--foo'];

      async layout(children, edges, constraints, styleMap) {

        // An array of LayoutChildren is passed into both the layout function,
        // and intrinsic sizes function below.
        const child = children[0];

        // You can query the any properties listed in "childInputProperties".
        const fooValue = child.styleMap.get('--foo');

        // And perform layout!
        const fragment = await child.layoutNextFragment({});

      }

      async intrinsicSizes(children, edges, styleMap) {

        // Or request the intrinsic size!
        const childIntrinsicSize = await children[0].intrinsicSizes();

      }
    });

A `LayoutChild` could be generated by:

- An element.

- A root inline box.

- A ::before or ::after pseudo-element.

  Note: Other pseudo-elements such as ::first-letter or ::first-line do not generate a `LayoutChild` for layout purposes. They are additional styling information for a text node.

- An anonymous box. For example an anonymous box may be inserted as a result of:

  - A text node which has undergone blockification. (Or more generally a root inline box which has undergone blockification).

  - An element with display: table-cell which doesn’t have a parent with display: table.

Note: As an example the following would be placed into three `LayoutChild`ren:

    <style>
      #box::before { content: 'hello!'; }
    </style>
    <div id="box">A block level box with text.</div>
    <img src="..." />

Note: As an example the following would be placed into a single `LayoutChild` as they share a root inline box:

    This is a next node, <span>with some additional styling,
    that may</span> break over<br>multiple lines.

Multiple non-atomic inlines are placed within the same `LayoutChild` to allow rendering engines to perform text shaping across element boundaries.

Note: As an example the following should produce one `LayoutFragment` but is from three non-atomic inlines:

    ع<span style="color: blue">ع</span>ع

Note: When accessing the `styleMap` the user agent can create a new `StylePropertyMapReadOnly` if none exists yet.

The `styleMap`, on getting from a `LayoutChild` this, the user agent must perform the following steps:

1. If this’ `[[styleMap]]` is null, then:

   1. Let box be this’ `[[box]]`.

   2. Let definition be the result of get a layout definition.

   3. Let childInputProperties be definition’s child input properties.

   4. Let styleMap be a new `StylePropertyMapReadOnly` populated with only the computed values for properties listed in childInputProperties for box.

   5. Set this’ `[[styleMap]]` internal slot to styleMap.

   Note: If the user agent always pre-populates `[[styleMap]]` then this branch of the algorithm won’t be reached.

2. Return this’ `StylePropertyMapReadOnly` contained in the `[[styleMap]]` internal slot.

Note: The `intrinsicSizes()` method allows the web developer to query the intrinsic sizes of the `LayoutChild`.

When the `intrinsicSizes()` method is called on a `LayoutChild` this, the user agent must perform the following steps:

1. Let p be a new promise.

2. Let context be the current layout’s layout API context.

3. If this’ `[[unique id]]` is not equal to context’s unique id, reject p with a "`InvalidStateError`" `DOMException`, and abort all these steps.

   Note: This is to ensure that only `LayoutChild`ren passed in as arguments to either the layout or intrinsicSizes method are used.

4. Let task be a new layout API work task with:

   - layout child being this.

   - task type being `"intrinsic-sizes"`.

   - promise being p.

5. Append task to context’s work queue.

6. Return p.

Note: The `layoutNextFragment()` method allows the web developer to produce a `LayoutFragment` for a given `LayoutChild` (the result of performing layout).

When the `layoutNextFragment(constraints, breakToken)` method is called on a `LayoutChild` this, the user agent must perform the following steps:

1. Let p be a new promise.

2. Let context be the current layout’s layout API context.

3. If this’ `[[unique id]]` is not equal to context’s unique id, reject p with a "`InvalidStateError`" `DOMException`, and abort all these steps.

   Note: This is to ensure that only `LayoutChild`ren passed in as arguments to either the layout or intrinsicSizes method are used.

4. If breakToken’s {{ChildBreakToken/[[unique id]]} is not equal to context’s unique id, reject p with a "`InvalidStateError`" `DOMException`, and abort all these steps.

5. If context’s mode is `"intrinsic-sizes"`, reject p with a "`NotSupportedError`" `DOMException`.

   Note: This is to ensure that inside a `intrinsicSizes` callback, `layoutNextFragment()` cannot be called.

6. Let task be a new layout API work task with:

   - layout constraints being constraints.

   - layout child being this.

   - child break token being breakToken.

   - task type being `"layout"`.

   - promise being p.

7. Append task to context’s work queue.

8. Return p.

#### 4.1.1. LayoutChildren and the Box Tree

Each box has a `[[layoutChildMap]]` internal slot, which is a map of `LayoutWorkletGlobalScope`s to `LayoutChild`ren.

Note: Get a layout child returns a `LayoutChild` object for the correct `LayoutWorkletGlobalScope` and creates one if it doesn’t exist yet.

When the user agent wants to get a layout child given workletGlobalScope, name, box, and uniqueId, it must run the following steps:

1. Assert that:

   - box is currently attached to the box tree.

   - box’s containing block is a layout API container.

   - The containing block’s layout() function’s first argument is name.

2. Let layoutChildMap be box’s `[[layoutChildMap]]`.

3. If layoutChildMap[workletGlobalScope] does not exist, run the following steps:

   1. Let definition be the result of get a layout definition given name, and workletGlobalScope.

      Assert that get a layout definition succeeded, and definition is not `"invalid"`.

   2. Let childInputProperties be definition’s child input properties.

   3. Let layoutChild be a new `LayoutChild` with internal slot(s):

      - `[[box]]` set to box.

      - `[[styleMap]]` set to a new `StylePropertyMapReadOnly` populated with only the computed values for properties listed in childInputProperties.

   4. Set layoutChildMap[workletGlobalScope] to layoutChild.

4. Let layoutChild be the result of get layoutChildMap[workletGlobalScope].

5. Set layoutChild’s `[[unique id]]` internal slot to uniqueId.

6. Return layoutChild.

When a box is inserted into the box tree the user agent may pre-populate the `[[layoutChildMap]]` for all `LayoutWorkletGlobalScope`s.

When a box is removed from the box tree the user agent must clear the `[[layoutChildMap]]`.

The user agent must clear the `[[layoutChildMap]]` internal slot every 1000 layout passes.

Note: The above rule exists to ensure that web developers do not rely on being able to store non-regeneratable state on the `LayoutChild` object. The 1000 limit was picked as a high upper bound, this limit may improve (downwards) over time.

When the user agent wants to update a layout child style given box, it must run the following steps:

1. Assert that:

   - box is currently attached to the box tree.

2. If box’s containing block is not a layout API container, abort all these steps.

3. Let layoutChildMap be box’s `[[layoutChildMap]]`.

4. For each layoutChild in layoutChildMap:

   1. layoutChild’s `[[styleMap]]` to null.

When the computed values of child input properties for a box changes the user agent must run the update a layout child style algorithm.

### 4.2. Layout Fragments

A `LayoutFragment` represents a CSS fragment of a `LayoutChild` after layout has occurred on that child. This is produced by the `layoutNextFragment()` method.

    [Exposed=LayoutWorklet]
    interface LayoutFragment {
        readonly attribute double inlineSize;
        readonly attribute double blockSize;

        attribute double inlineOffset;
        attribute double blockOffset;

        readonly attribute any data;

        readonly attribute ChildBreakToken? breakToken;
    };

The `LayoutFragment` has internal slot(s):

- `[[unique id]]` the unique id of the layout api context which produced this child fragment. This slot is used so that a `LayoutFragment` from a previous layout pass is invalid.

The `LayoutFragment` has `inlineSize` and `blockSize` attributes, which are set by the respective child’s layout algorithm. They represent the border box size of the CSS fragment, and are relative to the current layout’s writing mode.

The `inlineSize` and `blockSize` attributes cannot be changed. If the current layout requires a different `inlineSize` or `blockSize` the author must perform `layoutNextFragment()` again with different arguments in order to get different results.

The author inside the current layout can position a resulting `LayoutFragment` by setting its `inlineOffset` and `blockOffset` attributes. If not set by the author they default to zero. The `inlineOffset` and `blockOffset` attributes represent the position of the `LayoutFragment` relative to its parent’s border box, before transform or positioning (e.g. if a fragment is relatively positioned) has been applied.

A simple visualization showing positioning a `LayoutFragment` using `inlineOffset` and `blockOffset` in different writing modes.
The example below shows the basic usage of a `LayoutFragment`.

    registerLayout('example-layout-fragment', class {
      async layout(children, edges, constraints, styleMap) {

        // You must perform layout to generate a fragment.
        const fragment = await child.layoutNextFragment({});

        // You can query the size of the fragment produced:
        console.log(fragment.inlineSize);
        console.log(fragment.blockSize);

        // You can set the position of the fragment, e.g. this will set it to the
        // top-left corner:
        fragment.inlineOffset = edges.inlineStart;
        fragment.blockOffset = edges.blockStart;

        // Data may be passed from the child layout:
        console.log(fragment.data);

        // If the child fragmented, you can use the breakToken to produce the next
        // fragment in the chain.
        const nextFragment = await child.layoutNextFragment({}, fragment.breakToken);
      }
    });

A layout API container can communicate with other layout API containers by using the `data` attribute. This is set by the `data` member in the `FragmentResultOptions` dictionary.

The `LayoutFragment`'s `breakToken` specifies where the `LayoutChild` last fragmented. If the `breakToken` is null the `LayoutChild` wont produce any more `LayoutFragment`s for that token chain. The `breakToken` can be passed to the `layoutNextFragment()` function to produce the next `LayoutFragment` for a particular child. The `breakToken` cannot be changed. If the current layout requires a different `breakToken` the author must perform `layoutNextFragment()` again with different arguments.

### 4.3. Intrinsic Sizes

    [Exposed=LayoutWorklet]
    interface IntrinsicSizes {
      readonly attribute double minContentSize;
      readonly attribute double maxContentSize;
    };

A `IntrinsicSizes` object represents the min-content size and max-content size of a CSS box. It has `minContentSize` and `maxContentSize` attributes which represent the border box min/max-content contribution of the `LayoutChild` for the current layout. The attributes are relative to the inline direction of the current layout’s writing mode.

The `minContentSize` and `maxContentSize` cannot be changed. They must not change for a `LayoutChild` within the current layout pass.

The example below shows the border-box intrinsic sizes of two children.

    <style>
    .child-0 {
      width: 380px;
      border: solid 10px;
    }

    .child-1 {
      border: solid 5px;
    }

    .box {
      display: layout(intrinsic-sizes-example);
      font: 25px/1 Ahem;
    }
    </style>

    <div class="box">
      <div class="child-0"></div>
      <div class="child-1">XXX XXXX</div>
    </div>

    registerLayout('intrinsic-sizes-example', class {
        async intrinsicSizes(children, edges, styleMap) {
          const childrenSizes = await Promise.all(children.map((child) => {
              return child.intrinsicSizes();
          }));

          childrenSizes[0].minContentSize; // 400, (380+10+10) child has a fixed size.
          childrenSizes[0].maxContentSize; // 400, (380+10+10) child has a fixed size.

          childrenSizes[1].minContentSize; // 100, size of "XXXX".
          childrenSizes[1].maxContentSize; // 200, size of "XXX XXXX".
        }

        layout() {}
    });

### 4.4. Layout Constraints

A `LayoutConstraints` object is passed into the layout method which represents the all the constraints for the current layout to perform layout within.

    [Exposed=LayoutWorklet]
    interface LayoutConstraints {
        readonly attribute double availableInlineSize;
        readonly attribute double availableBlockSize;

        readonly attribute double? fixedInlineSize;
        readonly attribute double? fixedBlockSize;

        readonly attribute double percentageInlineSize;
        readonly attribute double percentageBlockSize;

        readonly attribute double? blockFragmentationOffset;
        readonly attribute BlockFragmentationType blockFragmentationType;

        readonly attribute any data;
    };

    enum BlockFragmentationType { "none", "page", "column", "region" };

The `LayoutConstraints` object has `availableInlineSize` and `availableBlockSize` attributes. This represents the available space for the current layout to respect.

Note: Some layouts may need to produce a `LayoutFragment` which exceed this size. For example a replaced element. The parent layout should expect this to occur and deal with it appropriately.

A parent layout may require the current layout to be exactly a particular size. If the `fixedInlineSize` or `fixedBlockSize` are specified the current layout should produce a `LayoutFragment` with a the specified size in the appropriate direction.

The `LayoutConstraints` object has `percentageInlineSize` and `percentageBlockSize` attributes. These represent the size that percentages should be resolved against while performing layout.

The `LayoutConstraints` has a `blockFragmentationType` attribute. The current layout should produce a `LayoutFragment` which fragments at the `blockFragmentationOffset` if possible.

The current layout can choose not to fragment a `LayoutChild` based on the `blockFragmentationType`, for example if the child has a property like break-inside: avoid-page;.

The example below shows the basic usage of the `LayoutConstraints` object.

    // The class below is registered with a "block-like" sizingMode, and can use the fixedInlineSize,
    // fixedBlockSize attributes.
    registerLayout('layout-constraints-example', class {
        async layout(children, edges, constraints, styleMap) {

            // Calculate the available size.
            const availableInlineSize = constraints.fixedInlineSize - edges.inline;
            const availableBlockSize = constraints.fixedBlockSize ?
                constraints.fixedBlockSize - edges.inline : null;

            // Web developers should resolve any percentages against the percentage sizes.
            const value = constraints.percentageInlineSize * 0.5;

        }
    });

The create a layout constraints object algorithm is used to create the `LayoutConstraints` object. Depending on the `sizing` it will either pre-calculate the `fixedInlineSize` and `fixedBlockSize` upfront.

When the user agent wants to create a layout constraints object given sizingMode, box, and internalLayoutConstraints, it must run the following steps:

1. If sizingMode is `"block-like"` then:

   1. Let fixedInlineSize be the result of calculating box’s border-box inline size (relative to box’s writing mode) exactly like block containers do.

   2. Let fixedBlockSize be null if box’s block size is unable to be calculated at this stage, (e.g. block size is auto), otherwise the result of calculating box’s border-box block size exactly like block containers do.

   3. Return a new `LayoutConstraints` object with:

      - `fixedInlineSize`, and `availableInlineSize` set to fixedInlineSize.

      - `percentageInlineSize` set to internalLayoutConstraints’ percentage resolution size in the inline axis (relative to box’s writing mode).

      - `fixedBlockSize` set to fixedBlockSize.

      - `availableBlockSize` set to fixedBlockSize if not null, otherwise internalLayoutConstraints’ available space in the block axis (relative to box’s writing mode).

      - `percentageBlockSize` set to internalLayoutConstraints’ percentage resolution size in the block axis (relative to box’s writing mode).

2. If sizingMode is `"manual"` then:

   1. Return a new `LayoutConstraints` object with:

      - `fixedInlineSize`/`fixedBlockSize` set to internalLayoutConstraints’ fixed inline/block size (relative to box’s writing mode) imposed by the parent layout. Either may be null.

        Note: See § 5.1 Sizing for different scenarios when this can occur.

      - `availableInlineSize`/`availableBlockSize` set to internalLayoutConstraints’ available space.

      - `percentageInlineSize`/`percentageBlockSize` set to internalLayoutConstraints’ percentage resolution size.

#### 4.4.1. Constraints for Layout Children

The `LayoutConstraintsOptions` dictionary represents the set of constraints which can be passed to a `LayoutChild` to produce a `LayoutFragment`.

    dictionary LayoutConstraintsOptions {
        double availableInlineSize;
        double availableBlockSize;

        double fixedInlineSize;
        double fixedBlockSize;

        double percentageInlineSize;
        double percentageBlockSize;

        double blockFragmentationOffset;
        BlockFragmentationType blockFragmentationType = "none";

        any data;
    };

Note: The translate a LayoutConstraintsOptions to internal constraints describes how to convert a `LayoutConstraintsOptions` object into a user agents internal representation.

When the user agent wants to translate a LayoutConstraintsOptions to internal constraints given options, it must run the following steps:

1. Let the available space in the inline direction (with respect to the current layout, be the result of:

   - If options’ `availableInlineSize` is not null, and `availableInlineSize` is greater than zero, let the result be `availableInlineSize`.

   - Otherwhise, let the result be zero.

2. Let the available space in the block direction (with respect to the current layout), be the result of:

   - If options’ `availableBlockSize` is not null, and `availableBlockSize` is greater than zero, let the result be `availableBlockSize`.

   - Otherwhise, let the result be zero.

3. Let the override size in the inline direction (with respect to the current layout, be the result of:

   - Let the result be options’ `fixedInlineSize`.

   Note: If the `fixedInlineSize` is null, no override size is applied.

4. Let the override size in the block direction (with respect to the current layout, be the result of:

   - Let the result be options’ `fixedBlockSize`.

   Note: If the `fixedBlockSize` is null, no override size is applied.

5. Let the percentage resultion size in the inline direction (with respect to the current layout, be the result of:

   - If options’ `percentageInlineSize` is not null, and `percentageInlineSize` is greater than zero, let the result be `percentageInlineSize`.

   - If options’ `availableInlineSize` is not null, and `availableInlineSize` is greater than zero, let the result be `availableInlineSize`.

   - Otherwhise, let the result be zero.

6. Let the percentage resultion size in the block direction (with respect to the current layout, be the result of:

   - If options’ `percentageBlockSize` is not null, and `percentageBlockSize` is greater than zero, let the result be `percentageBlockSize`.

   - If options’ `availableBlockSize` is not null, and `availableBlockSize` is greater than zero, let the result be `availableBlockSize`.

   - Otherwhise, let the result be zero.

7. If the child layout is a layout API container, then let the store the data (passed by `data`) be the result of:

   - Invoking StructuredSerializeForStorage on options’ `data`.

The example below shows the basic usage of the `LayoutConstraintsOptions` dictionary.

    // The class below is registered with a "block-like" sizingMode, and can use the
    // fixedInlineSize, fixedBlockSize attributes.
    registerLayout('child-layout-constraints-example', class {
        async layout(children, edges, constraints, styleMap) {

            // The call below gives the child an "available" space. It will try and
            // fit within this.
            const fragment = children[0].layoutNextFragment({
                availableInlineSize: 100,
                availableBlockSize: 200,
            });

            // The call below gives the child a "fixed" size, it will be forced to
            // this size ignoring any style set.
            const fragment = children[0].layoutNextFragment({
                fixedInlineSize: 20,
                fixedBlockSize: 30,
            });

        }
    });

### 4.5. Breaking and Fragmentation

A `LayoutChild` can produce multiple `LayoutFragment`s. A `LayoutChild` may fragment in the block direction if a `blockFragmentationType` is not none. Additionally `LayoutChild` which represents inline-level content, may fragment line by line if the layout options' `childDisplay` (set by `layoutOptions`) is `"normal"`.

    [Exposed=LayoutWorklet]
    interface ChildBreakToken {
        readonly attribute BreakType breakType;
        readonly attribute LayoutChild child;
    };

    [Exposed=LayoutWorklet]
    interface BreakToken {
        readonly attribute FrozenArray<ChildBreakToken> childBreakTokens;
        readonly attribute any data;
    };

    dictionary BreakTokenOptions {
        sequence<ChildBreakToken> childBreakTokens;
        any data = null;
    };

    enum BreakType { "none", "line", "column", "page", "region" };

The `ChildBreakToken` has internal slot(s):

- `[[unique id]]` the unique id of the layout api context which produced this child break token. This slot is used so that a `ChildBreakToken` from a previous layout pass is invalid.

A subsequent `LayoutFragment` is produced by using the previous `LayoutFragment`'s `breakToken`. This tells the child layout to produce a `LayoutFragment` starting at the point encoded in the `ChildBreakToken`.

### 4.6. Edges

A `LayoutEdges` object is passed into the layout method. This represents the sum of all the box model edges (border, scrollbar, padding), for the current box which is being laid out.

    [Exposed=LayoutWorklet]
    interface LayoutEdges {
      readonly attribute double inlineStart;
      readonly attribute double inlineEnd;

      readonly attribute double blockStart;
      readonly attribute double blockEnd;

      // Convenience attributes for the sum in one direction.
      readonly attribute double inline;
      readonly attribute double block;
    };

Each of the accessors represents the width in CSS pixels of an edge in each of the abstract dimensions (`inlineStart`, `inlineEnd`, `blockStart`, `blockEnd`).

The `inline`, and `block` on the `LayoutEdges` object are convenience attributes which represent the sum in that direction.

A visualization showing the `LayoutEdges` object for a box with different sized scrollbar, border, and padding.
This example shows an node styled by CSS, and what its respective `LayoutEdges` could contain.

    <style>
    .container {
      width: 50px;
      height: 50px;
    }

    .box {
      display: layout(box-edges);

      padding: 10%;
      border: solid 2px;
      overflow-y: scroll;
    }
    </style>

    <div class="container">
      <div class="box"></div>
    </div>

    registerLayout('box-edges', class {
        async layout(children, edges, constraints, styleMap, breakToken) {
            edges.inlineStart; // 2 + 5 (as 10% * 50px = 5px).
            edges.blockEnd; // 7 (2 + 5)
            edges.inlineEnd; // UA-dependent, due to scrollbar.
                             //  Could be 2 + 5 + 0 or 2 + 5 + 16 for example.
            edges.block; // 14 (2 + 5 + 5 + 2).
        }
    }

## 5. Interactions with other Modules

This section describes how other CSS modules interact with the CSS Layout API.

### 5.1. Sizing

User agents must use the `LayoutConstraints` object to communicate to the current layout the size they would like the fragment to be.

If the user agent wishes to force a size on the box, it can use the `fixedInlineSize` and `fixedBlockSize` attributes to do so.

The layout API container can be passed size information in different ways depending on the value of layout options' `sizing` (set by `layoutOptions` on the class).

If the value of layout options' `sizing` is `"block-like"`, then the `LayoutConstraints` passed to the layout API container:

- Must calculate and set `fixedInlineSize` based off the rules specified in [css-sizing-3] and the formatting context in which it participates, e.g.

  - As a block-level box in a block formatting context, it is sized like a block box that establishes a formatting context, with an auto inline size calculated as for non-replaced block boxes.

  - As an inline-level box in an inline formatting context, it is sized as an atomic inline-level box (such as an inline-block).

- Must calculate and set `fixedBlockSize` based off the rules specified in [css-sizing-3], and the formatting context in which it participates. If the layout API container has an auto block size, and cannot be determined ahead of time, `fixedBlockSize` must be set to `null`.

If the value of layout options' `sizing` is `"manual"`, then the user-agent must not pre-calculate `fixedInlineSize` and/or `fixedBlockSize` ahead of time, except when it is being forced to a particular size by the formatting context in which it participates, for example:

- If the layout API container is within a block formatting context, is inflow, and has an auto inline size, the user agent must set the `fixedInlineSize` to the stretch-fit inline size.

Note: In the example below the layout API container has its inline size set to 50.

    <style>
      #container {
        width: 100px;
        height: 100px;
        box-sizing: border-box;
        padding: 5px;
      }
      #layout-api {
        display: layout(foo);
        margin: 0 20px;
      }
    </style>
    <div id="container">
      <div id="layout-api"></div>
    </div>

#### 5.1.1. Positioned layout sizing

If a layout API container is out-of-flow positioned the user agent must solve the positioned size equations (CSS Positioned Layout 3 §8.1 The width of absolute or fixed positioned, non-replaced elements, CSS Positioned Layout 3 §8.3 The height of absolute or fixed positioned, non-replaced elements), and set the appropriate `fixedInlineSize` and `fixedBlockSize`.

Note: In the example below the layout API container has its inline and block size fixed to

    <style>
      #container {
        position: relative;
        width: 100px;
        height: 100px;
      }
      #layout-api {
        display: layout(foo);
        top: 10px;
        bottom: 10px;
        left: 10px;
        right: 10px;
        position: absolute;
      }
    </style>
    <div id="container">
      <div id="layout-api"></div>
    </div>

### 5.2. Positioning

All positioning in this level of the specification is handled by the user agent.

As a result:

- Out-of-flow children do not appear as `LayoutChild`ren.

- Layout API containers establish containing blocks exactly like block containers do. [CSS21]

- The `inlineOffset` and `blockOffset` represent the position of the fragment before any positioning and transforms have occured.

- The static position of an absolutely-positioned child of a layout API container is set to the inline-start, block-start padding edge of the layout API container. Auto margins are treated as zero for the child.

Note: In the example below:

- "child-relative" would be the only child passed to the author’s layout. If it was positioned at (`inlineOffset` `= 20`, `blockOffset` `= 30`), its final position would be (`25`, `40`) as the relative positioning was handled by the user agent.

- "child-absolute" would not appear as a `LayoutChild`, and instead would be laid out and positioned by the user agent.

- The examples above also apply in a similar way to sticky and fixed positioned children.

    <style>
      #container {
        display: layout(foo);
        position: relative; /* container is a containing block */
        width: 100px;
        height: 100px;
      }
      #child-relative {
        position: relative;
        left: 5px;
        top: 10px;
      }
    </style>
    <div id="container">
      <div id="child-relative"></div>
      <div id="child-absolute"></div>
    </div>

### 5.3. Overflow

The scrollable overflow for a layout API container is handled by the user agent in this level of the specification.

A layout API container should calculate its scrollable overflow exactly like block containers do.

Even if the author’s layout API container positions a fragment into the scrollable overflow region, relative positioning or transforms may cause the fragment to shift such that its scrollable overflow region, causing no overflow to occur.

### 5.4. Fragmentation

A parent layout can ask the current layout to fragment by setting the `blockFragmentationType` and `blockFragmentationOffset`.

E.g. [css-multicol-1] layout would set a `blockFragmentationType` to `"column"` and set the `blockFragmentationOffset` to where it needs the child to fragment.

### 5.5. Alignment

The first/last baseline sets of a layout API container is generated exactly like block containers do (see CSS Box Alignment 3 §9.1 Determining the Baselines of a Box). Except that the order of the in-flow children should be determined by the in which they are returned form the layout method (via `childFragments`) instead of the document order.

Note: In a future level of the specification there will be the ability for the author to define the baselines themselves. This will be of the form:

To query baseline information from a `LayoutChild`.

    const fragment = await child.layoutNextFragment({
      fixedInlineSize: availableInlineSize,
      baselineRequests: ['alphabetic', 'middle'],
    });
    fragment.baselines.get('alphabetic') === 25 /* or something */;

To produce baseline information for a parent layout:

    registerLayout('baseline-producing', class {
      async layout(children, edges, constraints, styleMap) {
        const result = {baselines: {}};

        for (let baselineRequest of constraints.baselineRequests) {
          // baselineRequest === 'alphabetic', or something else.
          result.baselines[baselineRequest] = 25;
        }

        return result;
      }
    });

## 6. Layout

This section describes how the CSS Layout API interacts with the user agent’s layout engine.

### 6.1. Processing Model

A layout API work task is a struct which describes the information needed by the user agent layout engine to perform layout work. It consists of:

- layout constraints a `LayoutConstraintsOptions`.

- layout child a `LayoutChild`.

- child break token a `ChildBreakToken`.

- task type which is either `"layout"`, or `"intrinsic-sizes"`

- promise a promise object.

A layout API context is a struct which describes the information needed by the current layout to produce either a fragment or determine the intrinsic-sizes for a box. It consits of:

- work queue which is a list of layout API work tasks. The user agent will alternate between processing these tasks, and running the microtask queue.

- unique id a internal unique identifier. This is used for determining that objects exposed to the web developer are only used within the correct layout pass. E.g. `LayoutFragment`s returned in the `FragmentResultOptions` dictionary belong to the current layout pass.

- mode which is either `"layout"`, or `"intrinsic-sizes"`. This is used for determining what the user agent layout engine is producing, and if a call to `layoutNextFragment()` is valid.

When the user agent wants to create a layout API context given mode, it must run the following steps:

1. Return a new layout API context with:

   - work queue being a new empty list.

   - unique id being a unique id.

   - mode being mode.

### 6.2. Performing Layout

The section describes how a user agent calls the web developer defined layout to produces intrinsic sizes, and fragments.

    // This is the final return value from the author defined layout() method.
    dictionary FragmentResultOptions {
        double inlineSize = 0;
        double blockSize = 0;
        double autoBlockSize = 0;
        sequence<LayoutFragment> childFragments = [];
        any data = null;
        BreakTokenOptions breakToken = null;
    };

    [Constructor(optional FragmentResultOptions options)]
    interface FragmentResult {
        readonly attribute double inlineSize;
        readonly attribute double blockSize;
    };

    dictionary IntrinsicSizesResultOptions {
        double maxContentSize;
        double minContentSize;
    };

The `FragmentResult` has internal slot(s):

- `[[box]]` a CSS box.

- `[[inline size]]` the inline size of the resulting fragment.

- `[[block size]]` the block size of the resulting fragment.

- `[[child fragments]]` the list of child fragments.

- `[[data]]` some optional serialized data.

- `[[internal break token]]` an internal representation of the break information for this fragment.

- `[[unique id]]` the unique id of the current layout api context. This slot is used so that a `FragmentResult` used outside the current layout pass is invalid.

The web developer defined layout method can return either a `FragmentResultOptions` or a `FragmentResult`. The `FragmentResult` can be used for determining the final size of the fragment or detecting if the provided `FragmentResultOptions` would result in triggering a fallback to flow layout.

This example show the web developer using the `FragmentResult` instead of just returning the `FragmentResultOptions` object.

    registerLayout('feature-detection', class {
        async layout(children, edges, constraints, styleMap, breakToken) {

          let result;
          try {
            result = new FragmentResult({
              childFragments: [],
              autoBlockSize: 100
            });
          } catch (e) {
            // The above call may throw, if the dictionary was just returned, it
            //  would fallback to flow layout.
          }

          // The web developer can test what size the fragment will be.
          result.blockSize;

          // Instead of returning the dictionary, we can just return this object.
          return result;
        }
    }

The `inlineSize`, on getting from a `FragmentResult` this, the user agent must perform the following steps:

1. Return this’ `[[inline size]]` internal slot.

The `blockSize`, on getting from a `FragmentResult` this, the user agent must perform the following steps:

1. Return this’ `[[block size]]` internal slot.

When the `FragmentResult(options)` constructor is called, the user agent must perform the following steps:

1. Let context be the current layout’s layout API context.

2. Return the result of construct a fragment result given context, and options.

Note: The construct a fragment result algorithm performs a series of validation checks (the web developer isn’t using an object from a previous invocation, and determines the final size of the resulting fragment.

When the user agent wants to construct a fragment result given context, and options the user agent must perform the following steps:

1. Let uniqueId be context’s unique id.

2. Let box be the current layout’s box.

3. Let breakTokenOptions be options’s `breakToken`.

4. For each childFragment in options’s `childFragments`, perform the following stubsteps:

   1. If childFragment’s `[[unique id]]` internal slot is not equal to uniqueId, then throw a TypeError, and abort all these steps.

5. For each childBreakToken in breakTokenOptions’s `childBreakTokens`, perform the following stubsteps:

   1. If childBreakToken’s `[[unique id]]` internal slot is not equal to uniqueId, then throw a TypeError, and abort all these steps.

6. If sizingMode is `"block-like"`:

   - Then:

     1. Let inlineSize be the result of calculating box’s border-box inline size (relative to box’s writing mode) exactly like block containers do.

     2. Let blockSize be the result of calculating box’s border-box block size (relative to box’s writing mode) exactly like block containers do, given fragment’s `autoBlockSize` as the "intrinsic block size".

   - Otherwise (sizingMode is `"manual"`):

     1. Let inlineSize be fragment’s `inlineSize`.

     2. Let blockSize be fragment’s `blockSize`.

7. Let clonedData be the result of invoking StructuredSerializeForStorage on options’s `data`.

8. Let clonedBreakTokenData be the result of invoking StructuredSerializeForStorage on breakTokenOptions’s `data`.

9. Let internalBreakToken be the internal representation of the fragmentation break containing clonedBreakTokenData, and breakTokenOptions.

10. Return a new `FragmentResult` with:

    - `[[box]]` being box.

    - `[[inline size]]` being inlineSize.

    - `[[block size]]` being blockSize.

    - `[[child fragments]]` being options’s `childFragments`.

    - `[[data]]` being clonedData.

    - `[[internal break token]]` being internalBreakToken.

    - `[[unique id]]` being uniqueId.

#### 6.2.1. Determining Intrinsic Sizes

The determine the intrinsic sizes algorithm defines how a user agent is to query the author defined layout for a box’s intrinsic sizes information.

Note: The determine the intrinsic sizes algorithm allows for user agents to cache an arbitrary number of previous invocations to reuse.

When the user agent wants to determine the intrinsic sizes of a layout API formatting context for a given box, childBoxes it must run the following steps:

1. Let layoutFunction be the layout() for the computed value of <display-inside> for box.

2. Let name be the first argument of the layoutFunction.

3. Let documentDefinition be the result of get a document layout definition given name.

   If get a document layout definition returned failure, or if documentDefinition is `"invalid"`, then let box fallback to the flow layout and abort all these steps.

4. Let workletGlobalScope be a `LayoutWorkletGlobalScope` from the list of worklet’s WorkletGlobalScopes from the layout `Worklet`, following the rules defined in § 6.2.3 Global Scope Selection.

   The user agent may also create a WorkletGlobalScope at this time, given the layout `Worklet`.

5. Run invoke an intrinsic sizes callback given name, box, childBoxes, and workletGlobalScope optionally in parallel.

   Note: If the user agent runs invoke an intrinsic sizes callback on a thread in parallel, it should select a layout worklet global scope which can be used on that thread.

When the user agent wants to invoke an intrinsic sizes callback given name, box, childBoxes, and workletGlobalScope, it must run the following steps:

1. Let definition be the result of get a layout definition given name, and workletGlobalScope.

   If get a layout definition returned failure, let the box fallback to the flow layout and abort all these steps.

2. Let layoutInstance be the result of get a layout class instance given box, definition, workletGlobalScope.

   If get a layout class instance returned failure, let the box fallback to the flow layout and abort all these steps.

3. Let inputProperties be definition’s input properties.

4. Let children be a new list.

5. For each childBox in childBoxes perform the following substeps:

   1. Let layoutChild be the result of get a layout child given workletGlobalScope, name, childBox, and context’s unique id.

   2. Append layoutChild to children.

6. Let edges be a new `LayoutEdges` populated with the computed value for all the box model edges for box.

7. Let styleMap be the result of get a style map given box, and inputProperties.

8. At this stage the user agent may re-use the intrinsic sizes from a previous invocation if children, edges, and styleMap are equivalent to that previous invocation. If so let the intrinsic sizes the cached intrinsic sizes and abort all these steps.

9. Let context be the result of create a layout API context given `"intrinsic-sizes"`.

10. Let intrinsicSizesFunction be definition’s intrinsic sizes function.

11. Let value be the result of Invoke(intrinsicSizesFunction, layoutInstance, «children, edges, styleMap»).

    If an exception is thrown the let box fallback to the flow layout and abort all these steps.

12. If value is a promise:

    - Then:

      1. Let intrinsicSizesValue be the result of run a work queue given value, and context’s work queue.

         If run a work queue returns failure, let the box fallback to the flow layout and abort all these steps.

    - Otherwise:

      1. Let intrinsicSizesValue be value.

13. Let intrinsicSizes be the result of converting intrinsicSizesValue to a `IntrinsicSizesResultOptions`. If an exception is thrown, let box fallback to the flow layout and abort all these steps.

14. Set the intrinsic sizes of box:

    - Let intrinsicSizes’s `minContentSize` be the min-content size of box.

    - Let intrinsicSizes’s `maxContentSize` be the max-content size of box.

#### 6.2.2. Generating Fragments

The generate a fragment algorithm defines how a user agent is to generate a box’s fragment for an author defined layout.

Note: The generate a fragment algorithm allows for user agents to cache an arbitrary number of previous invocations to reuse.

When the user agent wants to generate a fragment of a layout API formatting context for a given box, childBoxes, internalLayoutConstraints, and an optional internalBreakToken it must run the following steps:

1. Let layoutFunction be the layout() for the computed value of <display-inside> for box.

2. Let name be the first argument of the layoutFunction.

3. Let documentDefinition be the result of get a document layout definition given name.

   If get a document layout definition returned failure, or if documentDefinition is `"invalid"`, then let box fallback to the flow layout and abort all these steps.

4. Let workletGlobalScope be a `LayoutWorkletGlobalScope` from the list of worklet’s WorkletGlobalScopes from the layout `Worklet`, following the rules defined in § 6.2.3 Global Scope Selection.

   The user agent may also create a WorkletGlobalScope at this time, given the layout `Worklet`.

5. Run invoke a layout callback given name, box, childBoxes, internalLayoutConstraints, internalBreakToken, and workletGlobalScope optionally in parallel.

   Note: If the user agent runs invoke a layout callback on a thread in parallel, it should select a layout worklet global scope which can be used on that thread.

When the user agent wants to invoke a layout callback given name, box, childBoxes, internalLayoutConstraints, internalBreakToken, and workletGlobalScope, it must run the following steps:

1. Let definition be the result of get a layout definition given name, and workletGlobalScope.

   If get a layout definition returned failure, let the box fallback to the flow layout and abort all these steps.

2. Let layoutInstance be the result of get a layout class instance given box, definition, workletGlobalScope.

   If get a layout class instance returned failure, let the box fallback to the flow layout and abort all these steps.

3. Let context be the result of create a layout API context given `"layout"`.

4. Let sizingMode be definition’s layout options' `sizing` property.

5. Let inputProperties be definition’s input properties.

6. Let children be a new list.

7. For each childBox in childBoxes perform the following substeps:

   1. Let layoutChild be the result of get a layout child given workletGlobalScope, name, childBox, and context’s unique id.

   2. Append layoutChild to children.

8. Let edges be a new `LayoutEdges` populated with the computed value for all the box model edges for box.

9. Let layoutConstraints be the result of create a layout constraints object given internalLayoutConstraints, box, and sizingMode.

10. Let styleMap be the result of get a style map given box, and inputProperties.

11. Let breakToken be a new `BreakToken` populated with the appropriate information from internalBreakToken.

    If internalBreakToken is null, let breakToken be null.

12. At this stage the user agent may re-use a fragment from a previous invocation if children, styleMap, layoutConstraints, breakToken are equivalent to that previous invocation. If so let the fragment output be that cached fragment and abort all these steps.

13. Let layoutFunction be definition’s layout function.

14. Let value be the result of Invoke(layoutFunction, layoutInstance, «children, edges, layoutConstraints, styleMap, breakToken»).

    If an exception is thrown the let box fallback to the flow layout and abort all these steps.

15. If value is a promise:

    - Then:

      1. Let fragmentResultValue be the result of run a work queue given value.

         If run a work queue returns failure, let the box fallback to the flow layout and abort all these steps.

    - Otherwise:

      1. Let fragmentResultValue be value.

16. If fragmentResultValue is a platform object:

    - Then:

      1. Let fragmentResult be the result converting fragmentResultValue to a `FragmentResult`.

         If an exception is thrown, let box fallback to the flow layout and abort all these steps.

    - Otherwise:

      1. Let fragmentResultOptions be the result of converting fragmentResultValue to a `FragmentResultOptions`.

         If an exception is thrown, let box fallback to the flow layout and abort all these steps.

      2. Let fragmentResult be the result of construct a fragment result given fragmentResultOptions.

         If an exception is thrown, let box fallback to the flow layout and abort all these steps.

17. Return an internal representation of a fragment with:

    - The inline size set to fragmentResult’s `[[inline size]]`.

    - The block size set to fragmentResult’s `[[inline size]]`.

    - The child fragments set to fragmentResult’s `[[child fragments]]`.

      The ordering is important as this dictates their paint order (described in § 2 Layout API Containers). Their position relative to the border box of the fragment should be based off the author specified `inlineOffset` and `blockOffset`.

    - The fragmentation break information set to fragmentResult’s `[[internal break token]]`.

    - Store fragmentResult’s `[[data]]` with the fragment.

#### 6.2.3. Global Scope Selection

When the user agent needs to select a `LayoutWorkletGlobalScope` from the layout worklet’s WorkletGlobalScopes list it must:

- Select from at least two `LayoutWorkletGlobalScope`s, unless the user agent is under memory constraints.

- Not re-use the same `LayoutWorkletGlobalScope` more than 1000 times in a row.

  Note: The 1000 limit was picked as a high upper bound, this limit may improve (downwards) over time.

Note: These rules exist to ensure that authors do not rely on being able to store state on the global object or non-regeneratable state on the class. See Worklets 1 §1.2 Code Idempotency.

#### 6.2.4. Utility Algorithms

The section specifies algorithms common to the determine the intrinsic sizes and generate a fragment algorithms.

Note: Get a document layout definition returns a document layout definition from the owning document.

When the user agent wants to get a document layout definition given name, it must run the following steps:

1. Let documentLayoutDefinitionMap be the associated document’s document layout definitions map.

2. If documentLayoutDefinitionMap[name] does not exist, return failure and abort all these steps.

3. Return the result of get documentLayoutDefinitionMap[name].

Note: Get a layout definition returns a layout definition for a given `LayoutWorkletGlobalScope`, it the desired definition doesn’t exist it will "invalidate" the document layout definition, (so that the layout can’t be used again), and return failure.

When the user agent wants to get a layout definition given name, and workletGlobalScope, it must run the following steps:

1. Let layoutDefinitionMap be workletGlobalScope’s layout definitions map.

2. If layoutDefinitionMap[name] does not exist, run the following steps:

   1. Queue a task to run the following steps:

      1. Let documentLayoutDefinitionMap be the associated document’s document layout definition map.

      2. Set documentLayoutDefinitionMap[name] to `"invalid"`.

      3. The user agent should log an error to the debugging console stating that a class wasn’t registered in all `LayoutWorkletGlobalScope`s.

   2. Return failure, and abort all these steps.

3. Return the result of get layoutDefinitionMap[name].

Note: Get a layout class instance returns an instance of the web developer provided class. (Registered in `registerLayout()`). If one isn’t present yet, it will create a new one. This algorithm may fail, as the constructor may throw an exception.

When the user agent wants to get a layout class instance given box, definition, and workletGlobalScope, it must run the following steps:

1. Let layoutClassInstanceMap be box’s layout class instances map.

2. Let layoutInstance be the result of get layoutClassInstanceMap[workletGlobalScope]. If layoutInstance is null, run the following steps:

   1. If the constructor valid flag on definition is false, then return failure and abort all these steps.

   2. Let layoutCtor be the class constructor on definition.

   3. Let layoutInstance be the result of Construct(layoutCtor).

      If construct throws an exception, set the definition’s constructor valid flag to false, then return failure and abort all these steps.

   4. Set layoutClassInstanceMap[workletGlobalScope] to layoutInstance.

3. Return layoutInstance.

When the user agent wants to get a style map given box, and inputProperties, it must run the following steps:

1. If box’s styleMap is null, then:

   1. Let styleMap be a new `StylePropertyMapReadOnly` populated with only the computed values for properties listed in inputProperties for box.

   2. Set box’s styleMap internal slot to styleMap.

2. Return box’s `StylePropertyMapReadOnly` contained in the styleMap internal slot.

Run a work queue is designed to allow user agents to work in both a single threaded, and multi-threaded environment.

Note: Run a work queue processes layout api work tasks enqueued with `intrinsicSizes()` and `layoutNextFragment()`. It will continue processing tasks until the promise from the web developers layout or intrinsicSizes method is resolved, or the queue is empty after running the microtask queue.

The result of running the queue will either be the result of the layout or intrinsicSizes method, or failure.

When the user agent wants to run a work queue given promise, and workQueue, it must run the following steps:

1. If promise is not a promise, return failure.

2. While workQueue is not empty, and promise is pending:

   1. For each task in workQueue:

      1. Let layoutChild be task’s layout child.

      2. Let box be layoutChild’s box in the `[[box]]` internal slot.

      3. Let childPromise be task’s promise.

      4. If task’s task type is `"layout"`,

         - Then queue a task, or run synchronously, the following substeps:

           1. Let childConstraints be task’s layout constraints.

           2. Let childBreakToken be task’s child break token.

           3. Let targetRealm be layoutChild’s Realm.

           4. Let internalFragment be the result of the user agent producing a fragment based on box, childConstraints, and childBreakToken.

              Invoking translate a LayoutConstraintsOptions to internal constraints given childConstraints, must be run to translate the given `LayoutConstraintsOptions` into the internal constraints for the user agent’s layout engine.

           5. Let fragment be a new `LayoutFragment` with:

              - `inlineSize` being internalFragment’s inline size relative to the current layout’s writing mode.

              - `blockSize` being internalFragment’s block size relative to the current layout’s writing mode.

              - `inlineOffset` initially set to 0.

              - `blockOffset` initially set to 0.

              - `breakToken` being a new `ChildBreakToken` representing internalFragment’s internal break token, if any.

              - If internalFragment has a clonedData object stored with it, let `data` being the result of StructuredDeserialize(clonedData, targetRealm), otherwise null.

           6. Resolve childPromise with fragment.

         - Otherwise queue a task, or run synchronously, the following substeps:

           1. Let internalIntrinsicSizes be the result of the user agent calculating the border box min/max content contribution of box.

           2. Let intrinsicSizes be a new `IntrinsicSizes` with:

              - `minContentSize` being internalIntrinsicSizes’ border box min-content contribution, relative to the current layout’s writing mode.

              - `maxContentSize` being internalIntrinsicSizes’s border box max-content contribution, relative to the current layout’s writing mode.

           3. Resolve childPromise with intrinsicSizes.

   2. Wait (optionally in parallel) for all of the above tasks to complete.

      Note: If the tasks were perform synchronously, then this step is a no-op.

   3. Empty workQueue.

   4. Perform a microtask checkpoint.

3. If promise isn’t fulfilled (it is pending, or got rejected), return failure.

4. Return the fulfilled value of promise.

## 7. Examples

The layout algorithm below performs a block-like layout (positioning fragments sequentially in the block direction), while centering its children in the inline direction.

    registerLayout('block-like', class {
        async intrinsicSizes(children, edges, styleMap) {
          const childrenSizes = await Promise.all(children.map((child) => {
              return child.intrinsicSizes();
          }));

          const maxContentSize = childrenSizes.reduce((max, childSizes) => {
              return Math.max(max, childSizes.maxContentSize);
          }, 0) + edges.inline;

          const minContentSize = childrenSizes.reduce((max, childSizes) => {
              return Math.max(max, childSizes.minContentSize);
          }, 0) + edges.inline;

          return {maxContentSize, minContentSize};
        }

        async layout(children, edges, constraints, styleMap) {
            // Determine our (inner) available size.
            const availableInlineSize = constraints.fixedInlineSize - edges.inline;
            const availableBlockSize = constraints.fixedBlockSize ?
                constraints.fixedBlockSize - edges.block : null;

            const childFragments = [];
            const childConstraints = { availableInlineSize, availableBlockSize };

            const childFragments = await Promise.all(children.map((child) => {
                return child.layoutNextFragment(childConstraints);
            }));

            let blockOffset = edges.blockStart;
            for (let fragment of childFragments) {
                // Position the fragment in a block like manner, centering it in the
                // inline direction.
                fragment.blockOffset = blockOffset;
                fragment.inlineOffset = Math.max(
                    edges.inlineStart,
                    (availableInlineSize - fragment.inlineSize) / 2);

                blockOffset += fragment.blockSize;
            }

            const autoBlockSize = blockOffset + edges.blockEnd;

            return {
                autoBlockSize,
                childFragments,
            };
        }
    });

The layout algorithm performs a flexbox-like distribution of spare space in the inline direction. It creates child layout constraints which specify that a child should be a fixed inline size.

    registerLayout('flex-distribution-like', class {
        async intrinsicSizes(children, edges, styleMap) {
          const childrenSizes = await Promise.all(children.map((child) => {
              return child.intrinsicSizes();
          }));

          const maxContentSize = childrenSizes.reduce((sum, childSizes) => {
              return sum + childSizes.maxContentSize;
          }, 0) + edges.inline;

          const minContentSize = childrenSizes.reduce((max, childSizes) => {
              return sum + childSizes.minContentSize;
          }, 0) + edges.inline;

          return {maxContentSize, minContentSize};
        }

        async layout(children, edges, constraints, styleMap) {
            // Determine our (inner) available size.
            const availableInlineSize =
                constraints.fixedInlineSize - edges.inline;
            const availableBlockSize = constraints.fixedBlockSize ?
                constraints.fixedBlockSize - edges.block : null;

            const childConstraints = { availableInlineSize, availableBlockSize };

            const unconstrainedChildFragments = await Promise.all(children.map((child) => {
                return child.layoutNextFragment(childConstraints);
            }));

            const unconstrainedSizes = [];
            const totalSize = unconstrainedChildFragments.reduce((sum, fragment, i) => {
                unconstrainedSizes[i] = fragment.inlineSize;
                return sum + fragment.inlineSize;
            }, 0);

            // Distribute spare space between children.
            const remainingSpace = Math.max(0, inlineSize - totalSize);
            const extraSpace = remainingSpace / children.length;

            const childFragments = await Promise.all(children.map((child, i) => {
                return child.layoutNextFragment({
                    fixedInlineSize: unconstrainedSizes[i] + extraSpace,
                    availableBlockSize
                });
            }));

            // Position the fragments.
            let inlineOffset = 0;
            let maxChildBlockSize = 0;
            for (let fragment of childFragments) {
                fragment.inlineOffset = inlineOffset;
                fragment.blockOffset = edges.blockStart;

                inlineOffset += fragment.inlineSize;
                maxChildBlockSize = Math.max(maxChildBlockSize, fragment.blockSize);
            }

            return {
                autoBlockSize: maxChildBlockSize + edges.block,
                childFragments,
            };
        }
    });

This example shows a simple layout which indents child fragments for a certain number of lines.

This example also demonstrates using the previous `breakToken` of a `LayoutFragment` to produce the next fragment for the `LayoutChild`.

It also demonstrates using the `BreakToken` to respect the `LayoutConstraints`' `blockFragmentationType`, it resumes it layout from the previous `BreakToken`. It returns a `FragmentResultOptions` with a `breakToken` which is used to resume the layout.

    registerLayout('indent-lines', class {
        static layoutOptions = {childDisplay: 'normal'};
        static inputProperties = ['--indent', '--indent-lines'];

        async layout(children, edges, constraints, styleMap, breakToken) {
            // Determine our (inner) available size.
            const availableInlineSize =
                constraints.fixedInlineSize - edges.inline;
            const availableBlockSize = constraints.fixedBlockSize ?
                constraints.fixedBlockSize - edges.block : null;

            // Detrermine the number of lines to indent, and the indent amount.
            const indent = resolveLength(constraints, styleMap.get('--indent'));
            let lines = styleMap.get('--indent-lines').value;

            const childFragments = [];

            let childBreakToken = null;
            if (breakToken) {
                childBreakToken = breakToken.childBreakTokens[0];

                // Remove all the children we have already produced fragments for.
                children.splice(0, children.indexOf(childBreakToken.child));
            }

            let blockOffset = edges.blockStart;
            let child = children.shift();
            while (child) {
                const shouldIndent = lines-- > 0;

                // Adjust the inline size for the indent.
                const childAvailableInlineSize = shouldIndent ?
                    availableInlineSize - indent : availableInlineSize;

                const childConstraints = {
                    availableInlineSize: childAvailableInlineSize,
                    availableBlockSize,
                    percentageInlineSize: availableInlineSize,
                    blockFragmentationType: constraints.blockFragmentationType,
                };

                const fragment = await child.layoutNextFragment(childConstraints,
                                                                childBreakToken);
                childFragments.push(fragment);

                // Position the fragment.
                fragment.inlineOffset = shouldIndent ?
                    edges.inlineStart + indent : edges.inlineStart;
                fragment.blockOffset = blockOffset;
                blockOffset += fragment.blockSize;

                // Check if we have gone over the block fragmentation limit.
                if (constraints.blockFragmentationType != 'none' &&
                    blockOffset > constraints.blockSize) {
                    break;
                }

                if (fragment.breakToken) {
                    childBreakToken = fragment.breakToken;
                } else {
                    // If a fragment doesn’t have a break token, we move onto the
                    // next child.
                    child = children.shift();
                    childBreakToken = null;
                }
            }

            const autoBlockSize = blockOffset + edges.blockEnd;

            // Return our fragment.
            const result = {
                autoBlockSize,
                childFragments: childFragments,
            }

            if (childBreakToken) {
                result.breakToken = {
                    childBreakTokens: [childBreakToken],
                };
            }

            return result;
        }
    });

## 8. Security Considerations

There are no known security issues introduced by these features.

## 9. Privacy Considerations

There are no known privacy issues introduced by these features.

## Conformance

### Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with `class="example"`, like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with `class="note"`, like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with `<strong class="advisement">`, like this: UAs MUST provide an accessible alternative.

### Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
  A CSS style sheet.
renderer
  A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
  A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

### Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

#### Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

### Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

## Index

### Terms defined by this specification

- autoBlockSize, in §6.2
- availableBlockSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- availableInlineSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- "block", in §3.2
- block, in §4.6
- blockEnd, in §4.6
- blockFragmentationOffset
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- BlockFragmentationType, in §4.4
- blockFragmentationType
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- "block-like", in §3.2
- blockOffset, in §4.2
- [[block size]], in §6.2
- blockSize
  - attribute for FragmentResult, in §6.2
  - attribute for LayoutFragment, in §4.2
  - dict-member for FragmentResultOptions, in §6.2
- blockStart, in §4.6
- [[box]]
  - attribute for FragmentResult, in §6.2
  - attribute for LayoutChild, in §4.1
- BreakToken, in §4.5
- breakToken
  - attribute for LayoutFragment, in §4.2
  - dict-member for FragmentResultOptions, in §6.2
- BreakTokenOptions, in §4.5
- BreakType, in §4.5
- breakType, in §4.5
- child, in §4.5
- child break token, in §6.1
- ChildBreakToken, in §4.5
- childBreakTokens
  - attribute for BreakToken, in §4.5
  - dict-member for BreakTokenOptions, in §4.5
- childDisplay, in §3.2
- ChildDisplayType, in §3.2
- [[child fragments]], in §6.2
- childFragments, in §6.2
- child input properties
  - dfn for document layout definition, in §3.1
  - dfn for layout definition, in §3.1
- child layout, in §3.3
- class constructor, in §3.1
- "column"
  - enum-value for BlockFragmentationType, in §4.4
  - enum-value for BreakType, in §4.5
- construct a fragment result, in §6.2
- constructor valid flag, in §3.1
- create a layout API context, in §6.1
- create a layout constraints object, in §4.4
- current layout, in §3.3
- [[data]], in §6.2
- data
  - attribute for BreakToken, in §4.5
  - attribute for LayoutConstraints, in §4.4
  - attribute for LayoutFragment, in §4.2
  - dict-member for BreakTokenOptions, in §4.5
  - dict-member for FragmentResultOptions, in §6.2
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- determine the intrinsic sizes, in §6.2.1
- document layout definition, in §3.1
- document layout definitions, in §3.2
- fixedBlockSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- fixedInlineSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- FragmentResult, in §6.2
- FragmentResult(options), in §6.2
- FragmentResultOptions, in §6.2
- generate a fragment, in §6.2.2
- get a document layout definition, in §6.2.4
- get a layout child, in §4.1.1
- get a layout class instance, in §6.2.4
- get a layout definition, in §6.2.4
- get a style map, in §6.2.4
- inline, in §4.6
- inlineEnd, in §4.6
- inlineOffset, in §4.2
- [[inline size]], in §6.2
- inlineSize
  - attribute for FragmentResult, in §6.2
  - attribute for LayoutFragment, in §4.2
  - dict-member for FragmentResultOptions, in §6.2
- inlineStart, in §4.6
- input properties
  - dfn for document layout definition, in §3.1
  - dfn for layout definition, in §3.1
- [[internal break token]], in §6.2
- IntrinsicSizes, in §4.3
- intrinsicSizes(), in §4.1
- intrinsic sizes function, in §3.1
- IntrinsicSizesResultOptions, in §6.2
- invoke a layout callback, in §6.2.2
- invoke an intrinsic sizes callback, in §6.2.1
- layout(), in §2
- layout API container, in §2
- layout API context, in §6.1
- layout API formatting context, in §2
- layout API work task, in §6.1
- layout child, in §6.1
- LayoutChild, in §4.1
- [[layoutChildMap]], in §4.1.1
- layout class instances, in §3.2
- layout constraints, in §6.1
- LayoutConstraints, in §4.4
- LayoutConstraintsOptions, in §4.4.1
- layout definition, in §3.1
- layout definitions, in §3.2
- LayoutEdges, in §4.6
- LayoutFragment, in §4.2
- layout function, in §3.1
- layoutNextFragment(constraints, breakToken), in §4.1
- layout options
  - dfn for document layout definition, in §3.1
  - dfn for layout definition, in §3.1
- LayoutOptions, in §3.2
- LayoutSizingMode, in §3.2
- layoutWorklet, in §3
- LayoutWorkletGlobalScope, in §3
- "line", in §4.5
- "manual", in §3.2
- maxContentSize
  - attribute for IntrinsicSizes, in §4.3
  - dict-member for IntrinsicSizesResultOptions, in §6.2
- minContentSize
  - attribute for IntrinsicSizes, in §4.3
  - dict-member for IntrinsicSizesResultOptions, in §6.2
- mode, in §6.1
- "none"
  - enum-value for BlockFragmentationType, in §4.4
  - enum-value for BreakType, in §4.5
- "normal", in §3.2
- "page"
  - enum-value for BlockFragmentationType, in §4.4
  - enum-value for BreakType, in §4.5
- parent layout, in §3.3
- percentageBlockSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- percentageInlineSize
  - attribute for LayoutConstraints, in §4.4
  - dict-member for LayoutConstraintsOptions, in §4.4.1
- promise, in §6.1
- "region"
  - enum-value for BlockFragmentationType, in §4.4
  - enum-value for BreakType, in §4.5
- registerLayout(name, layoutCtor), in §3.2
- run a work queue, in §6.2.4
- sizing, in §3.2
- [[styleMap]], in §4.1
- styleMap
  - attribute for LayoutChild, in §4.1
  - definition of, in §3.2
- task type, in §6.1
- translate a LayoutConstraintsOptions to internal constraints, in §4.4.1
- [[unique id]]
  - attribute for ChildBreakToken, in §4.5
  - attribute for FragmentResult, in §6.2
  - attribute for LayoutChild, in §4.1
  - attribute for LayoutFragment, in §4.2
- unique id, in §6.1
- update a layout child style, in §4.1.1
- work queue, in §6.1

https://drafts.csswg.org/css-box-3/#propdef-margin Referenced in:

- 2. Layout API Containers

https://drafts.csswg.org/css-break-3/#propdef-break-inside Referenced in:

- 4.4. Layout Constraints

https://drafts.csswg.org/css-break-3/#fragment Referenced in:

- 1. Introduction
- 4.2. Layout Fragments (2)
- 5.4. Fragmentation
- 6.2.2. Generating Fragments (2) (3) (4)
- 6.2.4. Utility Algorithms

https://drafts.csswg.org/css-break-4/#fragmentation-break Referenced in:

- 6.2. Performing Layout
- 6.2.2. Generating Fragments

https://drafts.csswg.org/css-cascade-4/#computed-value Referenced in:

- 2. Layout API Containers
- 2.2. Box Tree Transformations
- 3.2. Registering A Layout
- 4.1. Layout Children (2)
- 4.1.1. LayoutChildren and the Box Tree (2)
- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

https://drafts.csswg.org/css-flexbox-1/#flex-container Referenced in:

- 2.2. Box Tree Transformations

https://drafts.csswg.org/css-grid-1/#grid-container Referenced in:

- 2.2. Box Tree Transformations

https://drafts.csswg.org/css-inline-3/#root-inline-box Referenced in:

- 2.2. Box Tree Transformations (2)
- 4.1. Layout Children (2) (3)

https://drafts.csswg.org/css-overflow-3/#propdef-overflow Referenced in:

- 2. Layout API Containers

https://drafts.csswg.org/css-overflow-3/#scrollable-overflow Referenced in:

- 5.3. Overflow (2) (3)

https://drafts.csswg.org/css-page-floats-3/#float Referenced in:

- 2.2. Box Tree Transformations

https://drafts.csswg.org/css-position-3/#valdef-z-index-auto Referenced in:

- 2.1. Layout API Container Painting

https://drafts.csswg.org/css-position-3/#propdef-position Referenced in:

- 2.1. Layout API Container Painting

https://drafts.csswg.org/css-position-3/#relative-position Referenced in:

- 4.2. Layout Fragments

https://drafts.csswg.org/css-position-3/#valdef-position-static Referenced in:

- 2.1. Layout API Container Painting

https://drafts.csswg.org/css-position-3/#propdef-z-index Referenced in:

- 2.1. Layout API Container Painting

https://drafts.csswg.org/css-pseudo-4/#selectordef-after Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-pseudo-4/#selectordef-before Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-pseudo-4/#selectordef-first-letter Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-pseudo-4/#selectordef-first-line Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-shapes-2/#valdef-shape-inside-display Referenced in:

- 2. Layout API Containers

https://drafts.csswg.org/css-sizing-3/#valdef-width-auto Referenced in:

- 4.4. Layout Constraints
- 5.1. Sizing (2) (3)

https://drafts.csswg.org/css-sizing-3/#available Referenced in:

- 4.4. Layout Constraints (2) (3)
- 4.4.1. Constraints for Layout Children (2)

https://drafts.csswg.org/css-sizing-3/#dfn-intrinsic-sizes Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2) (3)

https://drafts.csswg.org/css-sizing-3/#max-content Referenced in:

- 4.3. Intrinsic Sizes
- 6.2.1. Determining Intrinsic Sizes

https://drafts.csswg.org/css-sizing-3/#min-content Referenced in:

- 4.3. Intrinsic Sizes
- 6.2.1. Determining Intrinsic Sizes

https://drafts.csswg.org/css-sizing-3/#stretch-fit-inline-size Referenced in:

- 5.1. Sizing

https://drafts.css-houdini.org/css-typed-om-1/#stylepropertymapreadonly Referenced in:

- 3.2. Registering A Layout (2)
- 4.1. Layout Children (2) (3) (4) (5)
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.4. Utility Algorithms (2)

https://drafts.csswg.org/css-values-4/#typedef-ident Referenced in:

- 2. Layout API Containers

https://drafts.csswg.org/css-variables-1/#custom-property Referenced in:

- 3.2. Registering A Layout (2)

https://drafts.csswg.org/css-writing-modes-4/#abstract-dimensions Referenced in:

- 4.6. Edges

https://drafts.csswg.org/css-writing-modes-4/#block-size Referenced in:

- 4.4. Layout Constraints (2) (3)
- 5.1. Sizing
- 6.2. Performing Layout
- 6.2.2. Generating Fragments
- 6.2.4. Utility Algorithms

https://drafts.csswg.org/css-writing-modes-4/#block-start Referenced in:

- 5.2. Positioning

https://drafts.csswg.org/css-writing-modes-4/#inline-size Referenced in:

- 4.4. Layout Constraints
- 5.1. Sizing
- 6.2. Performing Layout
- 6.2.2. Generating Fragments
- 6.2.4. Utility Algorithms

https://drafts.csswg.org/css-writing-modes-4/#inline-start Referenced in:

- 5.2. Positioning

https://drafts.csswg.org/css-display-3/#typedef-display-inside Referenced in:

- 2. Layout API Containers (2)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

https://drafts.csswg.org/css-display-3/#typedef-display-outside Referenced in:

- 2.2. Box Tree Transformations (2)

https://drafts.csswg.org/css-display-3/#anonymous Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-display-3/#atomic-inline Referenced in:

- 2.2. Box Tree Transformations (2)
- 4.1. Layout Children (2)

https://drafts.csswg.org/css-display-3/#block-box Referenced in:

- 5.1. Sizing

https://drafts.csswg.org/css-display-3/#block-formatting-context Referenced in:

- 5.1. Sizing (2)

https://drafts.csswg.org/css-display-3/#block-level Referenced in:

- 2.2. Box Tree Transformations (2)
- 5.1. Sizing

https://drafts.csswg.org/css-display-3/#blockify Referenced in:

- 2.2. Box Tree Transformations (2)
- 4.1. Layout Children (2)

https://drafts.csswg.org/css-display-3/#blockify Referenced in:

- 2.2. Box Tree Transformations (2)
- 4.1. Layout Children (2)

https://drafts.csswg.org/css-display-3/#box Referenced in:

- 1. Introduction
- 3.2. Registering A Layout (2) (3) (4) (5) (6)
- 3.3. Terminology (2)
- 4.1. Layout Children (2)
- 4.1.1. LayoutChildren and the Box Tree (2) (3) (4)
- 4.3. Intrinsic Sizes
- 4.6. Edges
- 6.1. Processing Model
- 6.2. Performing Layout (2)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments
- 6.2.4. Utility Algorithms

https://drafts.csswg.org/css-display-3/#box tree Referenced in:

- 1. Introduction (2)
- 3.2. Registering A Layout
- 4.1.1. LayoutChildren and the Box Tree (2) (3) (4)

https://drafts.csswg.org/css-display-3/#containing-block Referenced in:

- 4.1.1. LayoutChildren and the Box Tree (2) (3)
- 5.2. Positioning

https://drafts.csswg.org/css-display-3/#propdef-display Referenced in:

- 2.2. Box Tree Transformations
- 4.1. Layout Children (2) (3)

https://drafts.csswg.org/css-display-3/#flow-layout Referenced in:

- 6.2. Performing Layout
- 6.2.1. Determining Intrinsic Sizes (2) (3) (4) (5) (6)
- 6.2.2. Generating Fragments (2) (3) (4) (5) (6) (7) (8)

https://drafts.csswg.org/css-display-3/#valdef-display-inline Referenced in:

- 2.2. Box Tree Transformations (2)

https://drafts.csswg.org/css-display-3/#inline-formatting-context Referenced in:

- 5.1. Sizing

https://drafts.csswg.org/css-display-3/#inline-level Referenced in:

- 2.2. Box Tree Transformations (2)
- 4.5. Breaking and Fragmentation
- 5.1. Sizing

https://drafts.csswg.org/css-display-3/#inlinify Referenced in:

- 2.2. Box Tree Transformations (2)

https://drafts.csswg.org/css-display-3/#valdef-display-none Referenced in:

- 4.1. Layout Children

https://drafts.csswg.org/css-display-3/#replaced-element Referenced in:

- 4.4. Layout Constraints

https://drafts.csswg.org/cssom-1/#namespacedef-css Referenced in:

- 3. Layout Worklet

https://drafts.csswg.org/cssom-1/#supported-css-property Referenced in:

- 3.2. Registering A Layout (2)

https://dom.spec.whatwg.org/#concept-document Referenced in:

- 3.1. Concepts
- 3.2. Registering A Layout (2)
- 6.2.4. Utility Algorithms (2) (3)

https://dom.spec.whatwg.org/#concept-element Referenced in:

- 4.1. Layout Children

https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint Referenced in:

- 6.2.4. Utility Algorithms

https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms (2) (3)

https://html.spec.whatwg.org/multipage/webappapis.html#concept-global-object-realm Referenced in:

- 6.2.4. Utility Algorithms

https://infra.spec.whatwg.org/#list-append Referenced in:

- 4.1. Layout Children (2)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

https://infra.spec.whatwg.org/#javascript-string-convert Referenced in:

- 3.2. Registering A Layout (2) (3) (4) (5)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments (2)

https://infra.spec.whatwg.org/#list-empty Referenced in:

- 6.1. Processing Model
- 6.2.4. Utility Algorithms (2)

https://infra.spec.whatwg.org/#map-exists Referenced in:

- 3.2. Registering A Layout (2)
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.4. Utility Algorithms (2)

https://infra.spec.whatwg.org/#map-iterate Referenced in:

- 4.1.1. LayoutChildren and the Box Tree

https://infra.spec.whatwg.org/#map-get Referenced in:

- 3.2. Registering A Layout
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.4. Utility Algorithms

https://infra.spec.whatwg.org/#list Referenced in:

- 3.1. Concepts (2) (3) (4)
- 6.1. Processing Model (2)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments
- 6.2.3. Global Scope Selection

https://infra.spec.whatwg.org/#ordered-map Referenced in:

- 3.2. Registering A Layout (2) (3) (4)
- 4.1.1. LayoutChildren and the Box Tree

https://infra.spec.whatwg.org/#map-set Referenced in:

- 3.2. Registering A Layout (2) (3)
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.4. Utility Algorithms (2)

https://infra.spec.whatwg.org/#struct Referenced in:

- 3.1. Concepts (2)
- 6.1. Processing Model (2)

https://infra.spec.whatwg.org/#iteration-while Referenced in:

- 6.2.4. Utility Algorithms

https://heycam.github.io/webidl/#idl-DOMException Referenced in:

- 3.2. Registering A Layout
- 4.1. Layout Children (2) (3) (4)

https://heycam.github.io/webidl/#idl-DOMString Referenced in:

- 3. Layout Worklet

https://heycam.github.io/webidl/#Exposed Referenced in:

- 3. Layout Worklet
- 3.2. Registering A Layout (2) (3)
- 4.1. Layout Children
- 4.2. Layout Fragments
- 4.3. Intrinsic Sizes
- 4.4. Layout Constraints
- 4.5. Breaking and Fragmentation (2)
- 4.6. Edges

https://heycam.github.io/webidl/#Global Referenced in:

- 3. Layout Worklet

https://heycam.github.io/webidl/#invalidmodificationerror Referenced in:

- 3.2. Registering A Layout

https://heycam.github.io/webidl/#invalidstateerror Referenced in:

- 4.1. Layout Children (2) (3)

https://heycam.github.io/webidl/#notsupportederror Referenced in:

- 4.1. Layout Children

https://heycam.github.io/webidl/#SameObject Referenced in:

- 3. Layout Worklet

https://heycam.github.io/webidl/#VoidFunction Referenced in:

- 3. Layout Worklet

https://heycam.github.io/webidl/#dfn-callback-function Referenced in:

- 3.2. Registering A Layout (2)

https://heycam.github.io/webidl/#idl-double Referenced in:

- 4.2. Layout Fragments (2) (3) (4)
- 4.3. Intrinsic Sizes (2)
- 4.4. Layout Constraints (2) (3) (4) (5) (6) (7)
- 4.4.1. Constraints for Layout Children (2) (3) (4) (5) (6) (7)
- 4.6. Edges (2) (3) (4) (5) (6)
- 6.2. Performing Layout (2) (3) (4) (5) (6) (7)

https://heycam.github.io/webidl/#invoke-a-callback-function Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

https://heycam.github.io/webidl/#dfn-platform-object Referenced in:

- 6.2.2. Generating Fragments

https://heycam.github.io/webidl/#dfn-throw Referenced in:

- 3.2. Registering A Layout (2) (3) (4) (5) (6)
- 6.2. Performing Layout (2)
- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2) (3) (4)

https://drafts.css-houdini.org/worklets/#worklet Referenced in:

- 3. Layout Worklet (2) (3)
- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)

https://drafts.css-houdini.org/worklets/#workletglobalscope Referenced in:

- 3. Layout Worklet

https://drafts.css-houdini.org/worklets/#create-a-workletglobalscope Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

https://drafts.css-houdini.org/worklets/#worklet-global-scope-type Referenced in:

- 3. Layout Worklet

https://drafts.css-houdini.org/worklets/#worklets-workletglobalscopes Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments
- 6.2.3. Global Scope Selection

### Terms defined by reference

- [css-box-3] defines the following terms:
  - margin
- [css-break-3] defines the following terms:
  - break-inside
  - fragment
- [css-break-4] defines the following terms:
  - fragmentation break
- [css-cascade-4] defines the following terms:
  - computed value
- [css-flexbox-1] defines the following terms:
  - flex container
- [css-grid-1] defines the following terms:
  - grid container
- [css-inline-3] defines the following terms:
  - root inline box
- [css-overflow-3] defines the following terms:
  - overflow
  - scrollable overflow
- [css-page-floats-3] defines the following terms:
  - float
- [css-position-3] defines the following terms:
  - auto
  - position
  - relatively position
  - static
  - z-index
- [css-pseudo-4] defines the following terms:
  - ::after
  - ::before
  - ::first-letter
  - ::first-line
- [css-shapes-2] defines the following terms:
  - display
- [css-sizing-3] defines the following terms:
  - auto
  - available space
  - intrinsic sizes
  - max-content size
  - min-content size
  - stretch-fit inline size
- [css-typed-om-1] defines the following terms:
  - StylePropertyMapReadOnly
- [css-values-4] defines the following terms:
  - <ident>
- [css-variables-1] defines the following terms:
  - custom property
- [css-writing-modes-4] defines the following terms:
  - abstract dimensions
  - block size
  - block-start
  - inline size
  - inline-start
- [css3-display] defines the following terms:
  - <display-inside>
  - <display-outside>
  - anonymous box
  - atomic inline
  - block box
  - block formatting context
  - block-level
  - blockification
  - blockify
  - box
  - box tree
  - containing block
  - display
  - flow layout
  - inline
  - inline formatting context
  - inline-level
  - inlinify
  - none
  - replaced element
- [cssom-1] defines the following terms:
  - CSS
  - supported css property
- [DOM] defines the following terms:
  - document
  - element
- [HTML] defines the following terms:
  - in parallel
  - perform a microtask checkpoint
  - queue a task
  - realm
- [INFRA] defines the following terms:
  - append
  - convert
  - empty
  - exist
  - for each (for map)
  - get
  - list
  - map
  - set
  - struct
  - while
- [WebIDL] defines the following terms:
  - DOMException
  - DOMString
  - Exposed
  - Global
  - InvalidModificationError
  - InvalidStateError
  - NotSupportedError
  - SameObject
  - VoidFunction
  - callback function
  - double
  - invoke
  - platform object
  - throw
- [worklets-1] defines the following terms:
  - Worklet
  - WorkletGlobalScope
  - create a workletglobalscope
  - worklet global scope type
  - worklet's workletglobalscopes

## References

### Normative References

[CSS-BOX-3]
  Elika Etemad. CSS Box Model Module Level 3. 18 December 2018. WD. URL: https://www.w3.org/TR/css-box-3/
[CSS-BREAK-3]
  Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. 4 December 2018. CR. URL: https://www.w3.org/TR/css-break-3/
[CSS-BREAK-4]
  Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 4. 18 December 2018. WD. URL: https://www.w3.org/TR/css-break-4/
[CSS-CASCADE-4]
  Elika Etemad; Tab Atkins Jr.. CSS Cascading and Inheritance Level 4. 28 August 2018. CR. URL: https://www.w3.org/TR/css-cascade-4/
[CSS-FLEXBOX-1]
  Tab Atkins Jr.; et al. CSS Flexible Box Layout Module Level 1. 19 November 2018. CR. URL: https://www.w3.org/TR/css-flexbox-1/
[CSS-GRID-1]
  Tab Atkins Jr.; Elika Etemad; Rossen Atanassov. CSS Grid Layout Module Level 1. 14 December 2017. CR. URL: https://www.w3.org/TR/css-grid-1/
[CSS-INLINE-3]
  Dave Cramer; Elika Etemad; Steve Zilles. CSS Inline Layout Module Level 3. 8 August 2018. WD. URL: https://www.w3.org/TR/css-inline-3/
[CSS-OVERFLOW-3]
  David Baron; Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. 31 July 2018. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-PAGE-FLOATS-3]
  Johannes Wilm. CSS Page Floats. 15 September 2015. WD. URL: https://www.w3.org/TR/css-page-floats-3/
[CSS-POSITION-3]
  Rossen Atanassov; Arron Eicholz. CSS Positioned Layout Module Level 3. 17 May 2016. WD. URL: https://www.w3.org/TR/css-position-3/
[CSS-PSEUDO-4]
  Daniel Glazman; Elika Etemad; Alan Stearns. CSS Pseudo-Elements Module Level 4. 25 February 2019. WD. URL: https://www.w3.org/TR/css-pseudo-4/
[CSS-SIZING-3]
  Tab Atkins Jr.; Elika Etemad. CSS Intrinsic & Extrinsic Sizing Module Level 3. 22 May 2019. WD. URL: https://www.w3.org/TR/css-sizing-3/
[CSS-TYPED-OM-1]
  Shane Stephens; Tab Atkins Jr.; Naina Raisinghani. CSS Typed OM Level 1. 10 April 2018. WD. URL: https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-4]
  Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 31 January 2019. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VARIABLES-1]
  Tab Atkins Jr.. CSS Custom Properties for Cascading Variables Module Level 1. 3 December 2015. CR. URL: https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
  Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. 24 May 2018. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS21]
  Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. REC. URL: https://www.w3.org/TR/CSS2/
[CSS3-DISPLAY]
  Tab Atkins Jr.; Elika Etemad. CSS Display Module Level 3. 28 August 2018. CR. URL: https://www.w3.org/TR/css-display-3/
[CSSOM-1]
  Simon Pieters; Glenn Adams. CSS Object Model (CSSOM). 17 March 2016. WD. URL: https://www.w3.org/TR/cssom-1/
[DOM]
  Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
  Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
  Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
  S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WebIDL]
  Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/
[WORKLETS-1]
  Ian Kilpatrick. Worklets Level 1. 7 June 2016. WD. URL: https://www.w3.org/TR/worklets-1/

### Informative References

[CSS-MULTICOL-1]
  Florian Rivoal; Rachel Andrew. CSS Multi-column Layout Module Level 1. 28 May 2018. WD. URL: https://www.w3.org/TR/css-multicol-1/
[CSS-SHAPES-2]
  CSS Shapes Module Level 2 URL: https://drafts.csswg.org/css-shapes-2/

## IDL Index

    partial namespace CSS {
        [SameObject] readonly attribute Worklet layoutWorklet;
    };

    [Global=(Worklet,LayoutWorklet),Exposed=LayoutWorklet]
    interface LayoutWorkletGlobalScope : WorkletGlobalScope {
        void registerLayout(DOMString name, VoidFunction layoutCtor);
    };

    [Exposed=LayoutWorklet]
    dictionary LayoutOptions {
      ChildDisplayType childDisplay = "block";
      LayoutSizingMode sizing = "block-like";
    };

    [Exposed=LayoutWorklet]
    enum ChildDisplayType {
        "block", // default - "blockifies" the child boxes.
        "normal",
    };

    [Exposed=LayoutWorklet]
    enum LayoutSizingMode {
        "block-like", // default - Sizing behaves like block containers.
        "manual", // Sizing is specified by the web developer.
    };

    [Exposed=LayoutWorklet]
    interface LayoutChild {
        readonly attribute StylePropertyMapReadOnly styleMap;

        Promise<IntrinsicSizes> intrinsicSizes();
        Promise<LayoutFragment> layoutNextFragment(LayoutConstraintsOptions constraints, ChildBreakToken breakToken);
    };

    [Exposed=LayoutWorklet]
    interface LayoutFragment {
        readonly attribute double inlineSize;
        readonly attribute double blockSize;

        attribute double inlineOffset;
        attribute double blockOffset;

        readonly attribute any data;

        readonly attribute ChildBreakToken? breakToken;
    };

    [Exposed=LayoutWorklet]
    interface IntrinsicSizes {
      readonly attribute double minContentSize;
      readonly attribute double maxContentSize;
    };

    [Exposed=LayoutWorklet]
    interface LayoutConstraints {
        readonly attribute double availableInlineSize;
        readonly attribute double availableBlockSize;

        readonly attribute double? fixedInlineSize;
        readonly attribute double? fixedBlockSize;

        readonly attribute double percentageInlineSize;
        readonly attribute double percentageBlockSize;

        readonly attribute double? blockFragmentationOffset;
        readonly attribute BlockFragmentationType blockFragmentationType;

        readonly attribute any data;
    };

    enum BlockFragmentationType { "none", "page", "column", "region" };

    dictionary LayoutConstraintsOptions {
        double availableInlineSize;
        double availableBlockSize;

        double fixedInlineSize;
        double fixedBlockSize;

        double percentageInlineSize;
        double percentageBlockSize;

        double blockFragmentationOffset;
        BlockFragmentationType blockFragmentationType = "none";

        any data;
    };

    [Exposed=LayoutWorklet]
    interface ChildBreakToken {
        readonly attribute BreakType breakType;
        readonly attribute LayoutChild child;
    };

    [Exposed=LayoutWorklet]
    interface BreakToken {
        readonly attribute FrozenArray<ChildBreakToken> childBreakTokens;
        readonly attribute any data;
    };

    dictionary BreakTokenOptions {
        sequence<ChildBreakToken> childBreakTokens;
        any data = null;
    };

    enum BreakType { "none", "line", "column", "page", "region" };

    [Exposed=LayoutWorklet]
    interface LayoutEdges {
      readonly attribute double inlineStart;
      readonly attribute double inlineEnd;

      readonly attribute double blockStart;
      readonly attribute double blockEnd;

      // Convenience attributes for the sum in one direction.
      readonly attribute double inline;
      readonly attribute double block;
    };

    // This is the final return value from the author defined layout() method.
    dictionary FragmentResultOptions {
        double inlineSize = 0;
        double blockSize = 0;
        double autoBlockSize = 0;
        sequence<LayoutFragment> childFragments = [];
        any data = null;
        BreakTokenOptions breakToken = null;
    };

    [Constructor(optional FragmentResultOptions options)]
    interface FragmentResult {
        readonly attribute double inlineSize;
        readonly attribute double blockSize;
    };

    dictionary IntrinsicSizesResultOptions {
        double maxContentSize;
        double minContentSize;
    };

#valdef-display-layout Referenced in:

- 2. Layout API Containers (2)
- 3.1. Concepts (2)
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#layout-api-container Referenced in:

- 2. Layout API Containers (2) (3) (4)
- 2.1. Layout API Container Painting
- 2.2. Box Tree Transformations
- 3.2. Registering A Layout (2)
- 4.1.1. LayoutChildren and the Box Tree (2)
- 4.2. Layout Fragments (2)
- 4.4.1. Constraints for Layout Children
- 5.1. Sizing (2) (3) (4) (5)
- 5.1.1. Positioned layout sizing (2)
- 5.2. Positioning (2) (3)
- 5.3. Overflow (2) (3)
- 5.5. Alignment

#layout-api-formatting-context Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#dom-css-layoutworklet Referenced in:

- 3. Layout Worklet (2) (3)

#layoutworkletglobalscope Referenced in:

- 3. Layout Worklet (2)
- 3.1. Concepts
- 3.2. Registering A Layout (2)
- 4.1.1. LayoutChildren and the Box Tree (2) (3)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments
- 6.2.3. Global Scope Selection (2) (3)
- 6.2.4. Utility Algorithms (2)

#layout-definition Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms

#layout-definition-class-constructor Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms

#layout-definition-layout-function Referenced in:

- 3.2. Registering A Layout
- 6.2.2. Generating Fragments

#layout-definition-intrinsic-sizes-function Referenced in:

- 3.2. Registering A Layout
- 6.2.1. Determining Intrinsic Sizes

#layout-definition-constructor-valid-flag Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms (2)

#layout-definition-input-properties Referenced in:

- 3.2. Registering A Layout
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#layout-definition-child-input-properties Referenced in:

- 3.2. Registering A Layout
- 4.1. Layout Children (2)
- 4.1.1. LayoutChildren and the Box Tree

#layout-definition-layout-options Referenced in:

- 3.2. Registering A Layout
- 6.2.2. Generating Fragments

#document-layout-definition Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms (2) (3)

#document-layout-definition-input-properties Referenced in:

- 3.2. Registering A Layout (2) (3)

#document-layout-definition-child-input-properties Referenced in:

- 3.2. Registering A Layout (2)
- 4.1.1. LayoutChildren and the Box Tree

#document-layout-definition-layout-options Referenced in:

- 2.2. Box Tree Transformations (2) (3)
- 3.2. Registering A Layout (2)
- 4.5. Breaking and Fragmentation
- 5.1. Sizing (2) (3)

#dictdef-layoutoptions Referenced in:

- 3.1. Concepts (2)
- 3.2. Registering A Layout

#dom-layoutoptions-childdisplay Referenced in:

- 2.2. Box Tree Transformations (2) (3)
- 4.5. Breaking and Fragmentation

#dom-layoutoptions-sizing Referenced in:

- 4.4. Layout Constraints
- 5.1. Sizing (2) (3)
- 6.2.2. Generating Fragments

#enumdef-childdisplaytype Referenced in:

- 3.2. Registering A Layout

#enumdef-layoutsizingmode Referenced in:

- 3.2. Registering A Layout

#document-layout-definitions Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms

#layout-definitions Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms

#layout-class-instances Referenced in:

- 6.2.4. Utility Algorithms

#stylemap Referenced in:

- 3.2. Registering A Layout
- 6.2.4. Utility Algorithms (2) (3)

#dom-layoutworkletglobalscope-registerlayout Referenced in:

- 3. Layout Worklet
- 3.1. Concepts
- 3.2. Registering A Layout (2) (3) (4)
- 6.2.4. Utility Algorithms

#current-layout Referenced in:

- 3.3. Terminology (2)
- 4.1. Layout Children (2)
- 4.2. Layout Fragments (2) (3)
- 4.3. Intrinsic Sizes (2)
- 4.4. Layout Constraints (2) (3) (4) (5) (6)
- 4.4.1. Constraints for Layout Children (2) (3) (4) (5) (6)
- 5.1. Sizing
- 5.4. Fragmentation
- 6.1. Processing Model
- 6.2. Performing Layout (2)
- 6.2.4. Utility Algorithms (2) (3) (4)

#parent-layout Referenced in:

- 4.4. Layout Constraints (2) (3)
- 5.4. Fragmentation
- 5.5. Alignment

#child-layout Referenced in:

- 4.4.1. Constraints for Layout Children
- 4.5. Breaking and Fragmentation

#layoutchild Referenced in:

- 2.2. Box Tree Transformations (2)
- 3.3. Terminology
- 4.1. Layout Children (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19)
- 4.1.1. LayoutChildren and the Box Tree (2) (3) (4)
- 4.2. Layout Fragments (2) (3)
- 4.3. Intrinsic Sizes (2)
- 4.4. Layout Constraints
- 4.4.1. Constraints for Layout Children
- 4.5. Breaking and Fragmentation (2) (3) (4)
- 5.2. Positioning (2)
- 5.5. Alignment
- 6.1. Processing Model
- 7. Examples

#dom-layoutchild-box-slot Referenced in:

- 4.1. Layout Children (2)
- 4.1.1. LayoutChildren and the Box Tree
- 6.2.4. Utility Algorithms

#dom-layoutchild-stylemap-slot Referenced in:

- 4.1. Layout Children (2) (3) (4) (5)
- 4.1.1. LayoutChildren and the Box Tree (2)

#dom-layoutchild-unique-id-slot Referenced in:

- 4.1. Layout Children (2)
- 4.1.1. LayoutChildren and the Box Tree

#dom-layoutchild-stylemap Referenced in:

- 4.1. Layout Children (2)

#dom-layoutchild-intrinsicsizes Referenced in:

- 4.1. Layout Children (2)
- 6.2.4. Utility Algorithms

#dom-layoutchild-layoutnextfragment Referenced in:

- 2.2. Box Tree Transformations
- 4.1. Layout Children (2) (3)
- 4.2. Layout Fragments (2) (3) (4)
- 6.1. Processing Model
- 6.2.4. Utility Algorithms

#dom-box-layoutchildmap-slot Referenced in:

- 4.1.1. LayoutChildren and the Box Tree (2) (3) (4) (5)

#get-a-layout-child Referenced in:

- 4.1.1. LayoutChildren and the Box Tree
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#update-a-layout-child-style Referenced in:

- 4.1.1. LayoutChildren and the Box Tree

#layoutfragment Referenced in:

- 2.2. Box Tree Transformations
- 4.1. Layout Children (2) (3) (4)
- 4.2. Layout Fragments (2) (3) (4) (5) (6) (7) (8) (9) (10) (11)
- 4.4. Layout Constraints (2) (3)
- 4.4.1. Constraints for Layout Children
- 4.5. Breaking and Fragmentation (2) (3) (4)
- 6.1. Processing Model
- 6.2. Performing Layout
- 6.2.4. Utility Algorithms
- 7. Examples

#dom-layoutfragment-inlinesize Referenced in:

- 4.2. Layout Fragments (2) (3)
- 6.2.4. Utility Algorithms

#dom-layoutfragment-blocksize Referenced in:

- 4.2. Layout Fragments (2) (3)
- 6.2.4. Utility Algorithms

#dom-layoutfragment-inlineoffset Referenced in:

- 4.2. Layout Fragments (2) (3)
- 5.2. Positioning (2)
- 6.2.2. Generating Fragments
- 6.2.4. Utility Algorithms

#dom-layoutfragment-blockoffset Referenced in:

- 4.2. Layout Fragments (2) (3)
- 5.2. Positioning (2)
- 6.2.2. Generating Fragments
- 6.2.4. Utility Algorithms

#dom-layoutfragment-data Referenced in:

- 4.2. Layout Fragments
- 6.2.4. Utility Algorithms

#dom-layoutfragment-breaktoken Referenced in:

- 4.2. Layout Fragments (2) (3) (4) (5)
- 4.5. Breaking and Fragmentation
- 6.2.4. Utility Algorithms
- 7. Examples

#dom-layoutfragment-unique-id-slot Referenced in:

- 6.2. Performing Layout

#intrinsicsizes Referenced in:

- 4.1. Layout Children
- 4.3. Intrinsic Sizes
- 6.2.4. Utility Algorithms

#dom-intrinsicsizes-mincontentsize Referenced in:

- 4.3. Intrinsic Sizes (2)
- 6.2.4. Utility Algorithms

#dom-intrinsicsizes-maxcontentsize Referenced in:

- 4.3. Intrinsic Sizes (2)
- 6.2.4. Utility Algorithms

#layoutconstraints Referenced in:

- 4.4. Layout Constraints (2) (3) (4) (5) (6) (7) (8)
- 5.1. Sizing (2)
- 7. Examples

#dom-layoutconstraints-availableinlinesize Referenced in:

- 4.4. Layout Constraints (2) (3)

#dom-layoutconstraints-availableblocksize Referenced in:

- 4.4. Layout Constraints (2) (3)

#dom-layoutconstraints-fixedinlinesize Referenced in:

- 4.4. Layout Constraints (2) (3) (4)
- 5.1. Sizing (2) (3) (4)
- 5.1.1. Positioned layout sizing

#dom-layoutconstraints-fixedblocksize Referenced in:

- 4.4. Layout Constraints (2) (3) (4)
- 5.1. Sizing (2) (3) (4)
- 5.1.1. Positioned layout sizing

#dom-layoutconstraints-percentageinlinesize Referenced in:

- 4.4. Layout Constraints (2) (3)

#dom-layoutconstraints-percentageblocksize Referenced in:

- 4.4. Layout Constraints (2) (3)

#dom-layoutconstraints-blockfragmentationoffset Referenced in:

- 4.4. Layout Constraints
- 5.4. Fragmentation (2)

#dom-layoutconstraints-blockfragmentationtype Referenced in:

- 4.4. Layout Constraints (2)
- 4.5. Breaking and Fragmentation
- 5.4. Fragmentation (2)
- 7. Examples

#dom-layoutconstraints-data Referenced in:

- 4.4.1. Constraints for Layout Children

#enumdef-blockfragmentationtype Referenced in:

- 4.4. Layout Constraints
- 4.4.1. Constraints for Layout Children

#create-a-layout-constraints-object Referenced in:

- 4.4. Layout Constraints
- 6.2.2. Generating Fragments

#dictdef-layoutconstraintsoptions Referenced in:

- 4.1. Layout Children
- 4.4.1. Constraints for Layout Children (2) (3)
- 6.1. Processing Model
- 6.2.4. Utility Algorithms

#dom-layoutconstraintsoptions-availableinlinesize Referenced in:

- 4.4.1. Constraints for Layout Children (2) (3) (4) (5) (6)

#dom-layoutconstraintsoptions-availableblocksize Referenced in:

- 4.4.1. Constraints for Layout Children (2) (3) (4) (5) (6)

#dom-layoutconstraintsoptions-fixedinlinesize Referenced in:

- 4.4.1. Constraints for Layout Children (2)

#dom-layoutconstraintsoptions-fixedblocksize Referenced in:

- 4.4.1. Constraints for Layout Children (2)

#dom-layoutconstraintsoptions-percentageinlinesize Referenced in:

- 4.4.1. Constraints for Layout Children (2) (3)

#dom-layoutconstraintsoptions-percentageblocksize Referenced in:

- 4.4.1. Constraints for Layout Children (2) (3)

#dom-layoutconstraintsoptions-data Referenced in:

- 4.4.1. Constraints for Layout Children

#translate-a-layoutconstraintsoptions-to-internal-constraints Referenced in:

- 4.4.1. Constraints for Layout Children
- 6.2.4. Utility Algorithms

#childbreaktoken Referenced in:

- 4.1. Layout Children
- 4.2. Layout Fragments
- 4.5. Breaking and Fragmentation (2) (3) (4) (5)
- 6.1. Processing Model
- 6.2.4. Utility Algorithms

#breaktoken Referenced in:

- 6.2.2. Generating Fragments
- 7. Examples (2)

#dictdef-breaktokenoptions Referenced in:

- 6.2. Performing Layout

#dom-breaktokenoptions-childbreaktokens Referenced in:

- 6.2. Performing Layout

#dom-breaktokenoptions-data Referenced in:

- 6.2. Performing Layout

#enumdef-breaktype Referenced in:

- 4.5. Breaking and Fragmentation

#dom-childbreaktoken-unique-id-slot Referenced in:

- 6.2. Performing Layout

#layoutedges Referenced in:

- 4.6. Edges (2) (3) (4)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#dom-layoutedges-inlinestart Referenced in:

- 4.6. Edges

#dom-layoutedges-inlineend Referenced in:

- 4.6. Edges

#dom-layoutedges-blockstart Referenced in:

- 4.6. Edges

#dom-layoutedges-blockend Referenced in:

- 4.6. Edges

#dom-layoutedges-inline Referenced in:

- 4.6. Edges

#dom-layoutedges-block Referenced in:

- 4.6. Edges

#layout-api-work-task Referenced in:

- 4.1. Layout Children (2)
- 6.1. Processing Model
- 6.2.4. Utility Algorithms

#layout-api-work-task-layout-constraints Referenced in:

- 4.1. Layout Children
- 6.2.4. Utility Algorithms

#layout-api-work-task-layout-child Referenced in:

- 4.1. Layout Children (2)
- 6.2.4. Utility Algorithms

#layout-api-work-task-child-break-token Referenced in:

- 4.1. Layout Children
- 6.2.4. Utility Algorithms

#layout-api-work-task-task-type Referenced in:

- 4.1. Layout Children (2)
- 6.2.4. Utility Algorithms

#layout-api-work-task-promise Referenced in:

- 4.1. Layout Children (2)
- 6.2.4. Utility Algorithms

#layout-api-context Referenced in:

- 4.1. Layout Children (2) (3)
- 4.2. Layout Fragments
- 4.5. Breaking and Fragmentation
- 6.1. Processing Model
- 6.2. Performing Layout (2)

#layout-api-context-work-queue Referenced in:

- 4.1. Layout Children (2)
- 6.1. Processing Model
- 6.2.1. Determining Intrinsic Sizes

#layout-api-context-unique-id Referenced in:

- 4.1. Layout Children (2) (3) (4)
- 4.2. Layout Fragments
- 4.5. Breaking and Fragmentation
- 6.1. Processing Model
- 6.2. Performing Layout (2)
- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#layout-api-context-mode Referenced in:

- 4.1. Layout Children
- 6.1. Processing Model

#create-a-layout-api-context Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#dictdef-fragmentresultoptions Referenced in:

- 4.2. Layout Fragments
- 6.1. Processing Model
- 6.2. Performing Layout (2) (3) (4)
- 6.2.2. Generating Fragments
- 7. Examples

#dom-fragmentresultoptions-inlinesize Referenced in:

- 6.2. Performing Layout

#dom-fragmentresultoptions-blocksize Referenced in:

- 6.2. Performing Layout

#dom-fragmentresultoptions-autoblocksize Referenced in:

- 6.2. Performing Layout

#dom-fragmentresultoptions-childfragments Referenced in:

- 2.1. Layout API Container Painting
- 5.5. Alignment
- 6.2. Performing Layout (2)

#dom-fragmentresultoptions-data Referenced in:

- 4.2. Layout Fragments
- 6.2. Performing Layout

#dom-fragmentresultoptions-breaktoken Referenced in:

- 6.2. Performing Layout
- 7. Examples

#fragmentresult Referenced in:

- 6.2. Performing Layout (2) (3) (4) (5) (6) (7) (8)
- 6.2.2. Generating Fragments

#dictdef-intrinsicsizesresultoptions Referenced in:

- 6.2.1. Determining Intrinsic Sizes

#dom-intrinsicsizesresultoptions-maxcontentsize Referenced in:

- 6.2.1. Determining Intrinsic Sizes

#dom-intrinsicsizesresultoptions-mincontentsize Referenced in:

- 6.2.1. Determining Intrinsic Sizes

#dom-fragmentresult-box-slot Referenced in:

- 6.2. Performing Layout

#dom-fragmentresult-inline-size-slot Referenced in:

- 6.2. Performing Layout (2)
- 6.2.2. Generating Fragments (2)

#dom-fragmentresult-block-size-slot Referenced in:

- 6.2. Performing Layout (2)

#dom-fragmentresult-child-fragments-slot Referenced in:

- 6.2. Performing Layout
- 6.2.2. Generating Fragments

#dom-fragmentresult-data-slot Referenced in:

- 6.2. Performing Layout
- 6.2.2. Generating Fragments

#dom-fragmentresult-internal-break-token-slot Referenced in:

- 6.2. Performing Layout
- 6.2.2. Generating Fragments

#dom-fragmentresult-unique-id-slot Referenced in:

- 6.2. Performing Layout

#dom-fragmentresult-inlinesize Referenced in:

- 6.2. Performing Layout

#dom-fragmentresult-blocksize Referenced in:

- 6.2. Performing Layout

#construct-a-fragment-result Referenced in:

- 6.2. Performing Layout (2)
- 6.2.2. Generating Fragments

#determine-the-intrinsic-sizes Referenced in:

- 3.2. Registering A Layout
- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.4. Utility Algorithms

#invoke-an-intrinsic-sizes-callback Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2)

#generate-a-fragment Referenced in:

- 3.2. Registering A Layout
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

#invoke-a-layout-callback Referenced in:

- 6.2.2. Generating Fragments (2)

#get-a-document-layout-definition Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

#get-a-layout-definition Referenced in:

- 4.1. Layout Children
- 4.1.1. LayoutChildren and the Box Tree (2)
- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

#get-a-layout-class-instance Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms

#get-a-style-map Referenced in:

- 6.2.1. Determining Intrinsic Sizes
- 6.2.2. Generating Fragments

#run-a-work-queue Referenced in:

- 6.2.1. Determining Intrinsic Sizes (2)
- 6.2.2. Generating Fragments (2)
- 6.2.4. Utility Algorithms (2)