Skip to content

Support last-baseline alignment (align-items: last baseline) in flexbox and grid - #1111

Open
nicoburns wants to merge 3 commits into
devin/1786752152-last-baseline-outputfrom
devin/1786752736-last-baseline-alignment
Open

Support last-baseline alignment (align-items: last baseline) in flexbox and grid#1111
nicoburns wants to merge 3 commits into
devin/1786752152-last-baseline-outputfrom
devin/1786752736-last-baseline-alignment

Conversation

@nicoburns

Copy link
Copy Markdown
Member

Objective

Implement last-baseline alignment (CSS align-items: last baseline / align-self: last baseline) in flexbox and grid layout, on top of the last-baseline output support in #1110 (this PR is based on that branch and should merge after it).

Context

Final PR of the last-baseline series (#1107#1108/#1109#1110 → this).

Style API (src/style/alignment.rs):

  • New AlignItemsKeyword::LastBaseline variant and AlignItems::LAST_BASELINE constant (serde name "LastBaseline").
  • CSS parsing accepts last baseline (and first baseline as an alias of baseline); safe/unsafe modifiers remain invalid with baseline keywords.

Flexbox (src/compute/flexbox.rs):

  • Items with align-self: last baseline form a second baseline group, separate from first-baseline items, using the same participation rules (no auto cross-axis margins, per flexbox §8.3).
  • calculate_children_base_lines now measures each group independently (skipping groups with ≤1 member), storing FlexItem::last_baseline with the same scroll-container border-box clamping as first baselines; missing baselines are synthesized from the border box.
  • Line cross-size calculation accounts for last-baseline groups via child.last_baseline + max_last_baseline_descent.
  • Cross-axis alignment anchors the last-baseline group to the cross-end of the line (mirroring how the first-baseline group anchors to cross-start), with wrap-reverse flipping as for first baselines:
    AlignItemsKeyword::LastBaseline => if constants.is_wrap_reverse {
        max_last_baseline - child.last_baseline
    } else {
        line_cross_size - max_last_baseline_descent - child.last_baseline
    }
  • In columns (where horizontal baselines can't be aligned along the cross axis), items synthesize baselines from their border boxes with the group anchored to the line's cross-end edge, matching Chrome's behaviour (verified via the generated align_last_baseline_column fixtures, including RTL).
  • The container's own last baseline now prefers items participating in last-baseline alignment (mirroring the first-baseline logic).
  • Absolutely positioned items treat last baseline like end for static position purposes.

Grid (src/compute/grid/):

  • GridItem gains a last_baseline_shim which acts as an extra bottom margin (the mirror image of the existing top-margin baseline_shim), applied both during intrinsic track sizing (margins_axis_sums_with_baseline_shims) and final alignment (align_and_position_item now takes a Line<f32> of top/bottom shims).
  • Track sizing computes shims per row for each baseline group independently; last-baseline shims are derived from each participating item's last-baseline descent (distance from its last baseline to the bottom of its margin box).
  • For positioning, LastBaseline falls back to End alignment within the grid area, which combined with the bottom shim aligns the items' last baselines.

Tests: 9 new gentest fixtures (36 generated tests) covering flex row/column/wrap-reverse/mixed-groups/auto-margin-exclusion and grid basic/nested/mixed-groups cases, plus parser and serde round-trip tests. cargo fmt, clippy, and the full test suite pass.

Feedback wanted

  • During track sizing, GridItem::last_baseline transiently stores the item's last-baseline descent rather than the baseline itself (documented on the field); it is overwritten with the real baseline from the item's final layout before the container's last baseline is computed. A separate field could be used instead if this overloading is deemed too subtle.
  • Flex column fallback behaviour for last baseline (left edges aligned, group anchored to the line's cross-end) was reverse-engineered from Chrome; other interpretations of the spec's fallback-alignment rules exist.

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/c0a80d9344d54e918b37cacfb71a2128
Requested by: @nicoburns

@staging-devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@staging-devin-ai-integration
staging-devin-ai-integration Bot force-pushed the devin/1786752736-last-baseline-alignment branch from 6a8e18b to 2aaa511 Compare August 19, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant