facebook / yoga

Yoga is an embeddable layout engine targeting web standards.

Home Page:https://yogalayout.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Measurement of absolute-positioned nodes

Omxjep3434 opened this issue · comments

Report

I am integrating Yoga with a custom layout system and I'm trying to better understand how absolute-positioned nodes are measured. I see some inconsistent behavior that could indicate bugs. I'm using the npm package version 3.0.4.

If everything is working as expected, feel free to close this issue.

Issues and Steps to Reproduce

function absolutePositionedMeasurements(yoga) {
    const config = yoga.Config.create();
    config.setPointScaleFactor(0);

    // Set up a simple parent/child layout, where the parent is the root of the layout calculation.
    const root = yoga.Node.createWithConfig(config);
    root.setWidth(10);
    root.setHeight(10);

    const child = yoga.Node.createWithConfig(config);
    root.insertChild(child, 0);

    // Set up a simple measure func to output the arguments.
    child.setMeasureFunc((width, widthMeasureMode, height, heightMeasureMode) => {
      console.log("Measure width: ", width, "Width Measure Mode: ", widthMeasureMode, "Measure height: ", height, "Height Measure Mode: ", heightMeasureMode);
      return { width, height };
    });

    // With a relative position type, the arguments are based on the containing block size and configuration (flexDirection, alignItems, etc.). Everything makes sense here.
    // Console output: Measure width:  10 Width Measure Mode:  2 Measure height:  10 Height Measure Mode:  1
    root.setFlexDirection(FlexDirection.Row);
    child.setPositionType(PositionType.Relative);
    root.calculateLayout(20, 20);

    // With an absolute position type, the arguments become NaN/undefined. I understand that this represents the max-content sizing type.
    // Console output: Measure width:  NaN Width Measure Mode:  0 Measure height:  NaN Height Measure Mode:  0
    root.setFlexDirection(FlexDirection.Row);
    child.setPositionType(PositionType.Absolute);
    root.calculateLayout(20, 20);

    // If the parent flex direction changes from 'row' to 'column', the width dimension is the fit-content sizing type while height remains max-content.
    // I can't make heads or tails of this. If the child is absolute and doesn't participate in the containing block's layout, why does the parent flex direction affect its measurement arguments?
    // Console output: Measure width:  10 Width Measure Mode:  2 Measure height:  NaN Height Measure Mode:  0
    root.setFlexDirection(FlexDirection.Column);
    child.setPositionType(PositionType.Absolute);
    child.markDirty();
    root.calculateLayout(20, 20);

    // Just one last observation. It seems that even constraints don't affect the measure arguments. Is this intentional?
    // Console output: Measure width:  10 Width Measure Mode:  2 Measure height:  NaN Height Measure Mode:  0
    child.setMaxWidth(5);
    child.setMaxHeight(5);
    root.setFlexDirection(FlexDirection.Column);
    child.setPositionType(PositionType.Absolute);
    root.calculateLayout(20, 20);   
}

function execute() {
  const yoga3 = await loadYoga();
  absolutePositionedMeasurements(yoga3);
}

My questions

  1. Are there any bugs in the behavior pointed out in my code snippet, or is everything working as expected?
  2. What is the measurement methodology for measuring an absolute-positioned node. When is an axis of the max-content sizing type (measure mode = undefined) and when is an axis of the fit-content sizing type (measure mode = at most)? I would expect a single sizing type to be used at all times. I'm not sure why the measure modes and sizes are different depending on the containing block's configuration, since an absolute-positioned node doesn't participate in the layout of the containing block.