From 1e0013a3bcfc9ce292695ce79c75936992b4b4e1 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Sat, 12 Jul 2025 13:51:10 +0200 Subject: [PATCH] LibWeb: Use margin box height for inline-block vertical alignment For `vertical-align: middle` and `vertical-align: text-bottom`, we used just the content height of the inline box to determine its alignment position. This caused incorrect positioning when padding is applied. This fixes the button alignment on our GitHub page. Fixes #290. --- Libraries/LibWeb/Layout/FormattingContext.cpp | 8 ++-- .../input-placeholder-with-line-height.txt | 22 +++++------ .../vertical-align-middle-with-padding.txt | 39 +++++++++++++++++++ .../vertical-align-middle-with-padding.html | 26 +++++++++++++ 4 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/vertical-align-middle-with-padding.txt create mode 100644 Tests/LibWeb/Layout/input/vertical-align-middle-with-padding.html diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index 18426f62440..f878cf6f450 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1803,8 +1803,8 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const // Top: Align the top of the aligned subtree with the top of the line box. return box_state.border_box_top(); case CSS::VerticalAlign::Middle: - // Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. - return box_state.content_height() / 2 + CSSPixels::nearest_value_for(box.containing_block()->first_available_font().pixel_metrics().x_height / 2); + // Middle: Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. + return box_state.margin_box_height() / 2 + CSSPixels::nearest_value_for(box.containing_block()->first_available_font().pixel_metrics().x_height / 2); case CSS::VerticalAlign::Bottom: // Bottom: Align the bottom of the aligned subtree with the bottom of the line box. return box_state.content_height() + box_state.margin_box_top(); @@ -1812,8 +1812,8 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const // TextTop: Align the top of the box with the top of the parent's content area (see 10.6.1). return box.computed_values().font_size(); case CSS::VerticalAlign::TextBottom: - // TextTop: Align the bottom of the box with the bottom of the parent's content area (see 10.6.1). - return box_state.content_height() - CSSPixels::nearest_value_for(box.containing_block()->first_available_font().pixel_metrics().descent * 2); + // TextBottom: Align the bottom of the box with the bottom of the parent's content area (see 10.6.1). + return box_state.margin_box_height() - CSSPixels::nearest_value_for(box.containing_block()->first_available_font().pixel_metrics().descent * 2); default: break; } diff --git a/Tests/LibWeb/Layout/expected/input-placeholder-with-line-height.txt b/Tests/LibWeb/Layout/expected/input-placeholder-with-line-height.txt index 1788119b934..c252b02d8e2 100644 --- a/Tests/LibWeb/Layout/expected/input-placeholder-with-line-height.txt +++ b/Tests/LibWeb/Layout/expected/input-placeholder-with-line-height.txt @@ -1,27 +1,27 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (0,0) content-size 800x100 [BFC] children: not-inline BlockContainer at (8,8) content-size 784x84 children: inline - frag 0 from BlockContainer start: 0, length: 0, rect: [9,8 200x82] baseline: 45.296875 - frag 1 from TextNode start: 0, length: 4, rect: [210,39 32.140625x18] baseline: 13.796875 + frag 0 from BlockContainer start: 0, length: 0, rect: [9,9 200x82] baseline: 46.296875 + frag 1 from TextNode start: 0, length: 4, rect: [210,40 32.140625x18] baseline: 13.796875 "text" - BlockContainer at (9,8) content-size 200x82 inline-block [BFC] children: not-inline - Box
at (11,9) content-size 196x80 flex-container(row) [FFC] children: not-inline - BlockContainer
at (11,9) content-size 98x80 flex-item [BFC] children: inline - frag 0 from TextNode start: 0, length: 11, rect: [11,9 89.90625x80] baseline: 44.796875 + BlockContainer at (9,9) content-size 200x82 inline-block [BFC] children: not-inline + Box
at (11,10) content-size 196x80 flex-container(row) [FFC] children: not-inline + BlockContainer
at (11,10) content-size 98x80 flex-item [BFC] children: inline + frag 0 from TextNode start: 0, length: 11, rect: [11,10 89.90625x80] baseline: 44.796875 "placeholder" TextNode <#text> - BlockContainer
at (109,9) content-size 98x80 flex-item [BFC] children: inline + BlockContainer
at (109,10) content-size 98x80 flex-item [BFC] children: inline TextNode <#text> TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x100] PaintableWithLines (BlockContainer) [8,8 784x84] - PaintableWithLines (BlockContainer) [8,7 202x84] - PaintableBox (Box
) [9,8 200x82] - PaintableWithLines (BlockContainer
) [11,9 98x80] + PaintableWithLines (BlockContainer) [8,8 202x84] + PaintableBox (Box
) [9,9 200x82] + PaintableWithLines (BlockContainer
) [11,10 98x80] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
) [109,9 98x80] + PaintableWithLines (BlockContainer
) [109,10 98x80] TextPaintable (TextNode<#text>) SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/vertical-align-middle-with-padding.txt b/Tests/LibWeb/Layout/expected/vertical-align-middle-with-padding.txt new file mode 100644 index 00000000000..f044ae131ef --- /dev/null +++ b/Tests/LibWeb/Layout/expected/vertical-align-middle-with-padding.txt @@ -0,0 +1,39 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x48 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x0 children: inline + BlockContainer at (8,8) content-size 32x32 floating [BFC] children: not-inline + BlockContainer at (9,9) content-size 30x30 children: inline + frag 0 from TextNode start: 0, length: 1, rect: [9,9 9.34375x18] baseline: 13.796875 + "B" + TextNode <#text> + TextNode <#text> + BlockContainer at (40,8) content-size 32.3125x40 floating [BFC] children: inline + frag 0 from BlockContainer start: 0, length: 0, rect: [51,19 10.3125x18] baseline: 24.296875 + BlockContainer at (51,19) content-size 10.3125x18 inline-block [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [51,19 10.3125x18] baseline: 13.796875 + "C" + TextNode <#text> + TextNode <#text> + BlockContainer at (72.3125,8) content-size 33.140625x40 floating [BFC] children: inline + frag 0 from BlockContainer start: 0, length: 0, rect: [83.3125,19 11.140625x18] baseline: 33.59375 + BlockContainer at (83.3125,19) content-size 11.140625x18 inline-block [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [83.3125,19 11.140625x18] baseline: 13.796875 + "D" + TextNode <#text> + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x48] + PaintableWithLines (BlockContainer) [8,8 784x0] overflow: [8,8 97.453125x40] + PaintableWithLines (BlockContainer
.a) [8,8 32x32] + PaintableWithLines (BlockContainer
.b) [8,8 32x32] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.a) [40,8 32.3125x40] + PaintableWithLines (BlockContainer.ib.c) [40,8 32.3125x40] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.a) [72.3125,8 33.140625x40] + PaintableWithLines (BlockContainer.ib.d) [72.3125,8 33.140625x40] + TextPaintable (TextNode<#text>) + +SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) + SC for BlockContainer [0,0 800x48] [children: 0] (z-index: auto) diff --git a/Tests/LibWeb/Layout/input/vertical-align-middle-with-padding.html b/Tests/LibWeb/Layout/input/vertical-align-middle-with-padding.html new file mode 100644 index 00000000000..26444fe9ebc --- /dev/null +++ b/Tests/LibWeb/Layout/input/vertical-align-middle-with-padding.html @@ -0,0 +1,26 @@ + + +
B
+
C
+
D