This article explains LayoutNG through a constraint-and-fragment model; the diagrams do not imply a single computation pass. Figures without an original experiment are not performance evidence.
1. Background: Why is LayoutNG needed?
Before 2020, Chrome used an older version of Blink Layout.
Question:
- Layout code 20+ years of historical baggage
- Block/Table/Flex/Grid are implemented individually
- Backflow propagation is uncontrollable
- Nested flex is prone to double calculations
- Floating point errors lead to repeated layout
To solve these problems, Chromium rewrote the layout engine:
LayoutNG
It is the next generation layout system for Chromium/Blink.
Goal:
- higher performance
- Less repetitive layout
- Predictable complexity
- More precise specification implementation
2. Performance issues with the old version of Flex
There are mainly 4 types of problems with the old algorithm:
1️⃣ Repeated Measurement
In the old implementation:
- flex-basis:auto
- min-content
- shrink
will result in:
👉 Child elements are measured multiple times
The process is similar:
测量 → 分配空间 → 不够 → 重新测量 → 再分配Nesting and repeated measurement may add cost, but growth depends on constraints and implementation rather than being universally exponential.
2️⃣ Backflow spread is uncontrollable
In old Blink:
- Parent container size changes
- May trigger re-layout of all child elements
- Changes in child elements may affect parent elements
Form:
Layout Ping-Pong
3️⃣ Non-uniform Layout Tree
In the old system:
- Block uses a set of logic
- Flex uses another set
- Table uses another set
Weak sharing ability → code duplication → difficulty in optimization
4️⃣ Floating point error problem
Appears after space allocation:
- 1px offset
- reflow correction again
Resulting in additional layout passes
3. The core design ideas of LayoutNG
LayoutNG introduces three core structures:
1️⃣ Constraint Space (constraint space)
Core idea:
Child elements no longer "guess their own size" Instead, the parent element gives a clear constraint space
It contains:
- available width
- Available height
- writing mode
- min/max
This way:
The child element layout is a pure function:
输入:Constraint Space
输出:FragmentPerformance implications:
- Avoid repeated measurements
- Results can be reused for matching constraints when cache-validity conditions hold
- Results can be cached
2️⃣ Fragment Tree
The old version of layout directly modifies the render tree.
LayoutNG:
- Do not modify nodes directly
- Generate fragment
- All layout results are written to the fragment tree
Benefits:
- Does not contaminate the original structure
- Can be rolled back
- Can be cached
- Avoid repeated DOM traversal
3️⃣ One-way data flow
Old version:
父 → 子
子 → 父
父再 → 子LayoutNG:
父传约束 → 子返回结果
结束Separating constraints from results helps reasoning and caching without eliminating sizing iterations.
This should not be equated with neural-network attention; the problems and constraints differ.
4. How does LayoutNG optimize Flex?
Now to the important points.
1️⃣ Reduce the number of measurements
Old version:
for each item:
measure min-content
measure max-contentLayoutNG:
- Only measure when you really need to
- Result caching
- Constraint is the same and can be reused directly
Equivalent to:
memoizationCaching and avoiding repeated work can improve specific pages, but do not establish a universal complexity reduction.
2️⃣ Smarter Free Space allocation algorithm
Flex grow/shrink is the most complicated part.
LayoutNG does:
- Precompute frozen items
- Allocation in batches
- Avoid repeated rollbacks
Older versions may:
分配 → 溢出 → 回退 → 再分配New version:
分配空间 → 检查 min/max 约束 → 必要时冻结项目并迭代Constraint handling may still require multiple distribution iterations; a single pass is not guaranteed.
3️⃣ Avoid nested explosion
Old version nesting:
Flex
└ Flex
└ FlexThe subtree is re-layout at each level.
LayoutNG:
- Subtree layout results are encapsulated as Fragment
- The parent layer only reads the dimensions
- Do not re-expand subtree
This greatly reduces nesting costs.
4️⃣ More accurate Dirty marking
The dirty granularity of the old system is coarse:
一个属性变 → 整个 subtree layoutLayoutNG:
- Accurately record affected nodes
- Use LayoutInvalidationReason
- Only relayout necessary nodes
For example:
Change the margin of a flex item:
Only affects:
- the item
- The flex container
instead of the entire page
5️⃣ Improve min/max content calculation
min-content is a Flex performance killer.
LayoutNG:
- Use unified intrinsic sizing algorithm
- Avoid repeated measurements
- Use higher precision float operations
Reduce the number of reflows.
5. Evidence needed for performance claims
The previous comparison table and figures such as 20%–40% and 2x lacked original test sources and have been withdrawn; they should not be attributed to Chromium as general findings.
Fix the browser, content, and constraints; compare layout counts, duration, and cache reuse, and retain traces. Architectural improvements and speedups on a particular page require different evidence.
6. A key breakthrough in LayoutNG
It turns Layout into:
"Functional Layout System"
Layout(node, constraint) → fragmentNo side effects
This means:
- Easier to parallelize (future)
- Easier to cache
- easier to debug
7. Why is Flex no longer a performance black hole?
Because:
- one-way constrained flow
- Fragment caching
- precise invalidation
- Avoid multiple rounds of shrink/grow
- Unify intrinsic calculations
Flex is still heavier than block,
But already:
From "uncertain complexity" to "predictable complexity"
8. How can you verify?
Open Chrome DevTools:
Performance → Record
Look:
- Layout time
- Layout invalidation
- Forced reflow
You will find:
The number of Flex layouts in modern Chrome is significantly less than in pre-2018 versions.
9. Final summary
Old version of Blink Flex:
State driven + two-way propagation + multi-round measurement
LayoutNG Flex:
Constraint-driven + one-way data flow + functional output
This is an architecture-level optimization.