Grid: skip contribution measurement when no spanned track can receive it - #1177
Merged
nicoburns merged 2 commits intoSep 3, 2026
Merged
Conversation
In the intrinsic track sizing steps for content-based minimums, max-content minimums, intrinsic maximums and max-content maximums, an item's min-/max- content contribution was measured for every item in the batch, and only then filtered by the track predicate inside distribute_item_space_*. Items spanning no track that the step applies to (e.g. only minmax(0, 1fr) or fixed tracks) therefore got measured under a min-content constraint for nothing. Blink checks the affected sets before computing the contribution; do the same.
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
… grid area size expand_flexible_tracks measured max-content with Size::NONE. This was masked because the contribution cache ignores the passed sizes and steps 2/3 had already measured every item with the real grid-area size. Now that those measurements are skipped for items spanning no affected track, the flexible-track step became the first measurer and text wrapped at an infinite width (WPT flex-content-resolution-rows-002). Route it through IntrinsicSizeMeasurer like the other contribution steps.
nicoburns
deleted the
devin/1788439473-grid-skip-unaffected-contributions
branch
September 3, 2026 14:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objective
In
resolve_intrinsic_track_sizes, the loops for "2. content-based minimums", "3. max-content minimums" (both the max-content-constraint variant and the unconditional one), "5. intrinsic maximums" and "6. max-content maximums" callitem_sizer.min_content_contribution/max_content_contributionfor every item in the batch, and only afterwards filter tracks via thetrack_is_affectedpredicate insidedistribute_item_space_to_*. Only step 1 (minimum_contribution) is gated on the spanned tracks.So an item spanning only tracks the step cannot apply to (e.g.
12.25rem minmax(0, 1fr)) still gets measured under a min-content constraint. That measurement is a full subtree measure and is then discarded. On Wikipedia's Vector skin (.mw-page-container-inner { grid-template-columns: 12.25rem minmax(0, 1fr) }) this measures the entire article underMinContent, inside which.mw-body'sminmax(0, 59.25rem)column legitimately collapses to 0, so every inline layout in the article is line-broken at width 0 (one word per line) for nothing.This PR moves the same predicate in front of the measurement:
Track sizing results are unchanged (the distribution step would have been a no-op for these items). All generated fixtures pass. New test
grid_item_spanning_only_unaffected_tracks_is_not_measured: 3 measurements onmain→ 1 (the final layout) with this change.Measured on a Blitz headless load of the Barack Obama Wikipedia article: zero-width
break_linespasses 916 → 3, first layout 845–862 ms → 592–626 ms, relayout 737–758 ms → 473–502 ms, live heap after layout 88.6 MB → 63.0 MB, layout geometry unchanged.Second commit:
expand_flexible_tracksmax-content measurementSkipping the step-2/3 measurements exposed a latent bug:
expand_flexible_tracks(11.7, indefinite free space) measured each item's max-content contribution withSize::NONEfor both grid area and available space (there was a TODO about it).max_content_contribution_cachedignores the sizes passed to it, so previously the cache was always pre-filled by steps 2/3 (which measure with the real grid-area size) and theSize::NONEnever took effect. With the skip, the flex step became the first measurer for items spanning e.g.50px/minmax(10px, 1fr), text was measured at an unconstrained width, and1frrows came out one line tall — WPTcss/css-grid/grid-definition/flex-content-resolution-rows-002.htmlwent 21/21 → 18/21 in Blitz.Fix: route the flex step through
IntrinsicSizeMeasurer::max_content_contributionlike every other contribution step (this also includes the item's margins, as the other steps do). New Chrome-generated fixturegrid_fr_row_max_content_uses_column_width(fails onmain+ first commit alone, passes now). WPT css-grid/css-flexbox/CSS2 in Blitz: no regressions vs Blitz main, +2 newly passing.Context
Blink does the same:
GridTrackSizingAlgorithm::IncreaseTrackSizesToAccommodateGridItemscollectssets_to_growviaIsContributionAppliedToSetandcontinues if empty before callingcontribution_size(...); additionallyResolveIntrinsicTrackSizesonly considers items withIsSpanningIntrinsicTrack. Spec: css-grid-2 §12.5 scopes each step to "items spanning tracks with a min/max track sizing function of …".Per-step predicates used:
min-content/max-contentauto(and max notmin-content) ormax-contentmax-contentRelated: DioxusLabs/blitz#835 repins Taffy to this branch and clamps negative inline available widths (a downstream symptom of the same discarded pass).
Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/3a0b8cc210c041d8955c841fb2a76a8e
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/3a0b8cc210c041d8955c841fb2a76a8e?variant=devin-insiders
Requested by: @nicoburns