LibWeb: Use margin box height for inline-block vertical alignment
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

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.
This commit is contained in:
Jelle Raaijmakers 2025-07-12 13:51:10 +02:00 committed by Andreas Kling
commit 1e0013a3bc
Notes: github-actions[bot] 2025-07-12 16:04:14 +00:00
4 changed files with 80 additions and 15 deletions

View file

@ -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;
}

View file

@ -1,27 +1,27 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x100 [BFC] children: not-inline
BlockContainer <body> 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 <input> at (9,8) content-size 200x82 inline-block [BFC] children: not-inline
Box <div> at (11,9) content-size 196x80 flex-container(row) [FFC] children: not-inline
BlockContainer <div> 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 <input> at (9,9) content-size 200x82 inline-block [BFC] children: not-inline
Box <div> at (11,10) content-size 196x80 flex-container(row) [FFC] children: not-inline
BlockContainer <div> 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 <div> at (109,9) content-size 98x80 flex-item [BFC] children: inline
BlockContainer <div> at (109,10) content-size 98x80 flex-item [BFC] children: inline
TextNode <#text>
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x100]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x84]
PaintableWithLines (BlockContainer<INPUT>) [8,7 202x84]
PaintableBox (Box<DIV>) [9,8 200x82]
PaintableWithLines (BlockContainer<DIV>) [11,9 98x80]
PaintableWithLines (BlockContainer<INPUT>) [8,8 202x84]
PaintableBox (Box<DIV>) [9,9 200x82]
PaintableWithLines (BlockContainer<DIV>) [11,10 98x80]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [109,9 98x80]
PaintableWithLines (BlockContainer<DIV>) [109,10 98x80]
TextPaintable (TextNode<#text>)
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)

View file

@ -0,0 +1,39 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x48 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x0 children: inline
BlockContainer <div.a> at (8,8) content-size 32x32 floating [BFC] children: not-inline
BlockContainer <div.b> 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 <div.a> 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 <span.ib.c> 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 <div.a> 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 <span.ib.d> 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<HTML>) [0,0 800x48]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x0] overflow: [8,8 97.453125x40]
PaintableWithLines (BlockContainer<DIV>.a) [8,8 32x32]
PaintableWithLines (BlockContainer<DIV>.b) [8,8 32x32]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.a) [40,8 32.3125x40]
PaintableWithLines (BlockContainer<SPAN>.ib.c) [40,8 32.3125x40]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.a) [72.3125,8 33.140625x40]
PaintableWithLines (BlockContainer<SPAN>.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<HTML> [0,0 800x48] [children: 0] (z-index: auto)

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<style>
.a {
float: left;
}
.b {
border: 1px solid blue;
height: 30px;
width: 30px;
}
.ib {
display: inline-block;
padding: 10px;
}
.c {
border: 1px solid red;
vertical-align: middle;
}
.d {
border: 1px solid purple;
vertical-align: text-bottom;
}
</style>
<div class="a"><div class="b">B</div></div>
<div class="a"><span class="ib c">C</span></div>
<div class="a"><span class="ib d">D</span></div>