mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 09:45:06 +02:00
CSS allows inline elements with `position: relative` (or other containing-block-establishing properties) to serve as the containing block for their absolutely positioned descendants. However, our layout system stores containing blocks as `Box*`, which cannot represent inline elements (they are `InlineNode`, not `Box`). This patch adds a workaround: when computing containing blocks, we also check if there's an inline element between the abspos element and its Box containing block that should actually be the CSS containing block. If found, we store it in a new member called `m_inline_containing_block_if_applicable` and use it during abspos layout to: 1. Compute the inline's fragment bounding box as the containing block rectangle (including padding, per CSS spec) 2. Resolve percentage-based insets against the inline's dimensions 3. Position the abspos element relative to the inline's location Some details to be aware of: - The inline containing block search happens in the function `recompute_containing_block()` by walking DOM ancestors (not layout tree ancestors, since the layout tree restructures blocks inside inlines as siblings) - For pseudo-elements like `::after`, we start the search from the generating element itself, since it may be the inline containing block - Fragment offsets are relative to their block container, so we translate the computed rect to the abspos element's containing block coordinate system by accumulating offsets up the ancestor chain - When the abspos element uses static position (auto insets), we don't apply the inline rect translation since static position is already computed in the correct coordinate system Long term, we want to refactor our "containing block" concept to map more cleanly to the spec concept. That means turning it into a rectangle instead of the box this rectangle was derived from. That's an invasive change for another day though.
25 lines
1.5 KiB
Plaintext
25 lines
1.5 KiB
Plaintext
Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline
|
|
BlockContainer <html> at [0,0] [0+0+0 800 0+0+0] [0+0+0 34 0+0+0] [BFC] children: not-inline
|
|
BlockContainer <body> at [8,8] [8+0+0 784 0+0+8] [8+0+0 18 0+0+8] children: not-inline
|
|
BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 18 0+0+0] children: inline
|
|
InlineNode <span> at [8,8] [0+0+0 74.125 16+0+0] [0+0+0 18 0+0+0]
|
|
frag 0 from TextNode start: 0, length: 8, rect: [8,8 74.125x18] baseline: 13.796875
|
|
"Features"
|
|
TextNode <#text> (not painted)
|
|
BlockContainer <(anonymous)> at [85.625,16.09375] positioned [0+0+0 8 0+0+0] [0+0+0 5 0+0+0] [BFC] children: inline
|
|
TextNode <#text> (not painted)
|
|
BlockContainer <(anonymous)> at [8,26] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline
|
|
TextNode <#text> (not painted)
|
|
|
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x34]
|
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x18]
|
|
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x18]
|
|
PaintableWithLines (InlineNode<SPAN>) [8,8 90.125x18]
|
|
TextPaintable (TextNode<#text>)
|
|
PaintableWithLines (BlockContainer(anonymous)) [85.625,16.09375 8x5]
|
|
PaintableWithLines (BlockContainer(anonymous)) [8,26 784x0]
|
|
|
|
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
|
|
SC for BlockContainer<HTML> [0,0 800x34] [children: 0] (z-index: auto)
|