瀏覽代碼

LibWeb: Fix percentage insets resolution for grid items

compute_inset() was incorrectly retrieving the containing block size
because containing_block() is unaware of grid areas that form a
containing block for grid items but do not exist in the layout tree.
With this change, we explicitly pass the containing block into
compute_inset(), allowing it to correctly provide the containing block
sizes for grid items.
Aliaksandr Kalenik 8 月之前
父節點
當前提交
a8c1d12e84

+ 5 - 3
Libraries/LibWeb/Layout/BlockFormattingContext.cpp

@@ -793,7 +793,8 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
     m_margin_state.add_margin(box_state.margin_bottom);
     m_margin_state.update_block_waiting_for_final_y_position();
 
-    compute_inset(box);
+    auto const& block_container_state = m_state.get(block_container);
+    compute_inset(box, content_box_rect(block_container_state).size());
 
     // Now that our children are formatted we place the ListItemBox with the left space we remembered.
     if (is<ListItemBox>(box)) {
@@ -1012,7 +1013,8 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
     auto& box_state = m_state.get_mutable(box);
     auto const& computed_values = box.computed_values();
 
-    resolve_vertical_box_model_metrics(box, m_state.get(block_container).content_width());
+    auto const& block_container_state = m_state.get(block_container);
+    resolve_vertical_box_model_metrics(box, block_container_state.content_width());
 
     compute_width(box, available_space);
 
@@ -1166,7 +1168,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
     if (line_builder)
         line_builder->recalculate_available_space();
 
-    compute_inset(box);
+    compute_inset(box, content_box_rect(block_container_state).size());
 
     if (independent_formatting_context)
         independent_formatting_context->parent_context_did_dimension_child_root_box();

+ 1 - 1
Libraries/LibWeb/Layout/FlexFormattingContext.cpp

@@ -176,7 +176,7 @@ void FlexFormattingContext::run(AvailableSpace const& available_space)
             if (auto independent_formatting_context = layout_inside(item.box, LayoutMode::Normal, item.used_values.available_inner_space_or_constraints_from(m_available_space_for_items->space)))
                 independent_formatting_context->parent_context_did_dimension_child_root_box();
 
-            compute_inset(item.box);
+            compute_inset(item.box, content_box_rect(m_flex_container_state).size());
         }
     }
 }

+ 3 - 3
Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -1328,7 +1328,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_replaced_elemen
 }
 
 // https://www.w3.org/TR/css-position-3/#relpos-insets
-void FormattingContext::compute_inset(NodeWithStyleAndBoxModelMetrics const& box)
+void FormattingContext::compute_inset(NodeWithStyleAndBoxModelMetrics const& box, CSSPixelSize containing_block_size)
 {
     if (box.computed_values().position() != CSS::Positioning::Relative)
         return;
@@ -1363,8 +1363,8 @@ void FormattingContext::compute_inset(NodeWithStyleAndBoxModelMetrics const& box
     auto const& computed_values = box.computed_values();
 
     // FIXME: Respect the containing block's writing-mode.
-    resolve_two_opposing_insets(computed_values.inset().left(), computed_values.inset().right(), box_state.inset_left, box_state.inset_right, containing_block_width_for(box));
-    resolve_two_opposing_insets(computed_values.inset().top(), computed_values.inset().bottom(), box_state.inset_top, box_state.inset_bottom, containing_block_height_for(box));
+    resolve_two_opposing_insets(computed_values.inset().left(), computed_values.inset().right(), box_state.inset_left, box_state.inset_right, containing_block_size.width());
+    resolve_two_opposing_insets(computed_values.inset().top(), computed_values.inset().bottom(), box_state.inset_top, box_state.inset_bottom, containing_block_size.height());
 }
 
 // https://drafts.csswg.org/css-sizing-3/#fit-content-size

+ 1 - 1
Libraries/LibWeb/Layout/FormattingContext.h

@@ -106,7 +106,7 @@ public:
 
     bool can_skip_is_anonymous_text_run(Box&);
 
-    void compute_inset(NodeWithStyleAndBoxModelMetrics const&);
+    void compute_inset(NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize containing_block_size);
 
 protected:
     FormattingContext(Type, LayoutMode, LayoutState&, Box const&, FormattingContext* parent = nullptr);

+ 3 - 2
Libraries/LibWeb/Layout/GridFormattingContext.cpp

@@ -2060,8 +2060,9 @@ void GridFormattingContext::run(AvailableSpace const& available_space)
     for (auto& grid_item : m_grid_items) {
         auto& grid_item_box_state = m_state.get_mutable(grid_item.box);
         CSSPixelPoint margin_offset = { grid_item_box_state.margin_box_left(), grid_item_box_state.margin_box_top() };
-        grid_item_box_state.offset = get_grid_area_rect(grid_item).top_left() + margin_offset;
-        compute_inset(grid_item.box);
+        auto const grid_area_rect = get_grid_area_rect(grid_item);
+        grid_item_box_state.offset = grid_area_rect.top_left() + margin_offset;
+        compute_inset(grid_item.box, grid_area_rect.size());
 
         auto available_space_for_children = AvailableSpace(AvailableSize::make_definite(grid_item_box_state.content_width()), AvailableSize::make_definite(grid_item_box_state.content_height()));
         if (auto independent_formatting_context = layout_inside(grid_item.box, LayoutMode::Normal, available_space_for_children))

+ 1 - 1
Libraries/LibWeb/Layout/InlineFormattingContext.cpp

@@ -294,7 +294,7 @@ void InlineFormattingContext::generate_line_boxes()
         }
         case InlineLevelIterator::Item::Type::Element: {
             auto& box = verify_cast<Layout::Box>(*item.node);
-            compute_inset(box);
+            compute_inset(box, content_box_rect(m_containing_block_used_values).size());
             if (containing_block().computed_values().white_space() != CSS::WhiteSpace::Nowrap) {
                 auto minimum_space_needed_on_line = item.border_box_width();
                 if (item.margin_start < 0)

+ 1 - 1
Libraries/LibWeb/Layout/InlineLevelIterator.cpp

@@ -48,7 +48,7 @@ void InlineLevelIterator::enter_node_with_box_model_metrics(Layout::NodeWithStyl
     m_extra_leading_metrics->padding += used_values.padding_left;
 
     // Now's our chance to resolve the inset properties for this node.
-    m_inline_formatting_context.compute_inset(node);
+    m_inline_formatting_context.compute_inset(node, m_inline_formatting_context.content_box_rect(m_containing_block_used_values).size());
 
     m_box_model_node_stack.append(node);
 }

+ 54 - 0
Tests/LibWeb/Layout/expected/grid/relative-position-grid-item-with-percentage-insets.txt

@@ -0,0 +1,54 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x318 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x302 children: not-inline
+      Box <div.grid-container> at (9,9) content-size 300x300 [GFC] children: not-inline
+        BlockContainer <(anonymous)> (not painted) [BFC] children: inline
+          TextNode <#text>
+        Box <div.grid-item> at (20,20) content-size 123x123 flex-container(row) [FFC] children: not-inline
+          BlockContainer <(anonymous)> at (58.140625,73) content-size 46.71875x17 flex-item [BFC] children: inline
+            frag 0 from TextNode start: 0, length: 6, rect: [58.140625,73 46.71875x17] baseline: 13.296875
+                "Item 1"
+            TextNode <#text>
+        BlockContainer <(anonymous)> (not painted) [BFC] children: inline
+          TextNode <#text>
+        Box <div.grid-item.relative-item> at (247.5,97.5) content-size 123x123 positioned flex-container(row) [FFC] children: not-inline
+          BlockContainer <(anonymous)> at (284.40625,150.5) content-size 49.1875x17 flex-item [BFC] children: inline
+            frag 0 from TextNode start: 0, length: 6, rect: [284.40625,150.5 49.1875x17] baseline: 13.296875
+                "Item 2"
+            TextNode <#text>
+        BlockContainer <(anonymous)> (not painted) [BFC] children: inline
+          TextNode <#text>
+        Box <div.grid-item> at (20,175) content-size 123x123 flex-container(row) [FFC] children: not-inline
+          BlockContainer <(anonymous)> at (56.765625,228) content-size 49.46875x17 flex-item [BFC] children: inline
+            frag 0 from TextNode start: 0, length: 6, rect: [56.765625,228 49.46875x17] baseline: 13.296875
+                "Item 3"
+            TextNode <#text>
+        BlockContainer <(anonymous)> (not painted) [BFC] children: inline
+          TextNode <#text>
+        Box <div.grid-item> at (175,175) content-size 123x123 flex-container(row) [FFC] children: not-inline
+          BlockContainer <(anonymous)> at (212.4375,228) content-size 48.125x17 flex-item [BFC] children: inline
+            frag 0 from TextNode start: 0, length: 6, rect: [212.4375,228 48.125x17] baseline: 13.296875
+                "Item 4"
+            TextNode <#text>
+        BlockContainer <(anonymous)> (not painted) [BFC] children: inline
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (8,310) content-size 784x0 children: inline
+        TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x318]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x302]
+      PaintableBox (Box<DIV>.grid-container) [8,8 302x302] overflow: [9,9 372.5x300]
+        PaintableBox (Box<DIV>.grid-item) [9,9 145x145]
+          PaintableWithLines (BlockContainer(anonymous)) [58.140625,73 46.71875x17]
+            TextPaintable (TextNode<#text>)
+        PaintableBox (Box<DIV>.grid-item.relative-item) [236.5,86.5 145x145]
+          PaintableWithLines (BlockContainer(anonymous)) [284.40625,150.5 49.1875x17]
+            TextPaintable (TextNode<#text>)
+        PaintableBox (Box<DIV>.grid-item) [9,164 145x145]
+          PaintableWithLines (BlockContainer(anonymous)) [56.765625,228 49.46875x17]
+            TextPaintable (TextNode<#text>)
+        PaintableBox (Box<DIV>.grid-item) [164,164 145x145]
+          PaintableWithLines (BlockContainer(anonymous)) [212.4375,228 48.125x17]
+            TextPaintable (TextNode<#text>)
+      PaintableWithLines (BlockContainer(anonymous)) [8,310 784x0]

+ 33 - 0
Tests/LibWeb/Layout/input/grid/relative-position-grid-item-with-percentage-insets.html

@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+.grid-container {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: 10px;
+    width: 300px;
+    height: 300px;
+    border: 1px solid #ccc;
+}
+
+.grid-item {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #eee;
+    border: 1px solid #aaa;
+    padding: 10px;
+}
+
+.relative-item {
+    position: relative;
+    left: 50%;
+    top: 50%;
+    background-color: #cce;
+}
+</style>
+<div class="grid-container">
+    <div class="grid-item">Item 1</div>
+    <div class="grid-item relative-item">Item 2</div>
+    <div class="grid-item">Item 3</div>
+    <div class="grid-item">Item 4</div>
+</div>