Преглед изворни кода

LibWeb: Treat % max-height as none when containing block size indefinite

Fixes #19371
Andreas Kling пре 2 година
родитељ
комит
43e1343abf

+ 46 - 0
Tests/LibWeb/Layout/expected/percentage-max-height-when-containing-block-has-indefinite-height.txt

@@ -0,0 +1,46 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (1,1) content-size 798x123.34375 [BFC] children: not-inline
+    BlockContainer <body> at (10,10) content-size 780x105.34375 children: not-inline
+      BlockContainer <div.block.formatting-context> at (11,11) content-size 778x19.46875 [BFC] children: not-inline
+        BlockContainer <div> at (12,12) content-size 776x17.46875 children: inline
+          line 0 width: 40.671875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 5, rect: [12,12 40.671875x17.46875]
+              "block"
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (10,31.46875) content-size 780x0 children: inline
+        TextNode <#text>
+      BlockContainer <div.inline.formatting-context> at (11,32.46875) content-size 778x17.46875 [BFC] children: inline
+        line 0 width: 43.296875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+          frag 0 from TextNode start: 0, length: 6, rect: [12,32.46875 41.296875x17.46875]
+            "inline"
+        InlineNode <div>
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (10,50.9375) content-size 780x0 children: inline
+        TextNode <#text>
+      Box <div.flex.formatting-context> at (11,51.9375) content-size 778x19.46875 flex-container(row) [FFC] children: not-inline
+        BlockContainer <div> at (12,52.9375) content-size 29.09375x17.46875 flex-item [BFC] children: inline
+          line 0 width: 29.09375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 4, rect: [12,52.9375 29.09375x17.46875]
+              "flex"
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (10,72.40625) content-size 780x0 children: inline
+        TextNode <#text>
+      Box <div.grid.formatting-context> at (11,73.40625) content-size 778x19.46875 [GFC] children: not-inline
+        BlockContainer <div> at (12,74.40625) content-size 776x17.46875 [BFC] children: inline
+          line 0 width: 28.8125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 4, rect: [12,74.40625 28.8125x17.46875]
+              "grid"
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (10,93.875) content-size 780x0 children: inline
+        TextNode <#text>
+      TableWrapper <(anonymous)> at (10,93.875) content-size 38.625x21.46875 [BFC] children: not-inline
+        Box <div.table.formatting-context> at (11,94.875) content-size 38.625x19.46875 table-box [TFC] children: not-inline
+          Box <(anonymous)> at (11,94.875) content-size 40.625x19.46875 table-row children: not-inline
+            BlockContainer <(anonymous)> at (11,94.875) content-size 40.625x19.46875 table-cell [BFC] children: not-inline
+              BlockContainer <div> at (12,95.875) content-size 38.625x17.46875 children: inline
+                line 0 width: 38.625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+                  frag 0 from TextNode start: 0, length: 5, rect: [12,95.875 38.625x17.46875]
+                    "table"
+                TextNode <#text>
+      BlockContainer <(anonymous)> at (10,115.34375) content-size 780x0 children: inline
+        TextNode <#text>

+ 32 - 0
Tests/LibWeb/Layout/input/percentage-max-height-when-containing-block-has-indefinite-height.html

@@ -0,0 +1,32 @@
+<!DOCTYPE html><style>
+* {
+    border: 1px solid black;
+}
+.formatting-context > div {
+    max-height: 100%;
+    background-color: orange;
+}
+.inline.formatting-context > div {
+    display: inline;
+}
+.block {
+    display: block flow-root;
+}
+.inline {
+    display: block flow-root;
+}
+.flex {
+    display: block flex;
+}
+.grid {
+    display: block grid;
+}
+.table {
+    display: block table;
+}
+</style>
+<div class="block formatting-context"><div>block</div></div>
+<div class="inline formatting-context"><div>inline</div></div>
+<div class="flex formatting-context"><div>flex</div></div>
+<div class="grid formatting-context"><div>grid</div></div>
+<div class="table formatting-context"><div>table</div></div>

+ 1 - 1
Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp

@@ -458,7 +458,7 @@ void BlockFormattingContext::compute_height(Box const& box, AvailableSpace const
         }
     }
 
-    if (!computed_values.max_height().is_none()) {
+    if (!should_treat_max_height_as_none(box)) {
         auto max_height = calculate_inner_height(box, available_space.height, computed_values.max_height());
         if (!max_height.is_auto())
             height = min(height, max_height.to_px(box));

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

@@ -268,7 +268,7 @@ CSSPixelSize FormattingContext::solve_replaced_size_constraint(CSSPixels input_w
     CSSPixels specified_min_width = box.computed_values().min_width().is_auto() ? 0 : box.computed_values().min_width().to_px(box, width_of_containing_block);
     CSSPixels specified_max_width = box.computed_values().max_width().is_none() ? input_width : box.computed_values().max_width().to_px(box, width_of_containing_block);
     CSSPixels specified_min_height = box.computed_values().min_height().is_auto() ? 0 : box.computed_values().min_height().to_px(box, height_of_containing_block);
-    CSSPixels specified_max_height = box.computed_values().max_height().is_none() ? input_height : box.computed_values().max_height().to_px(box, height_of_containing_block);
+    CSSPixels specified_max_height = should_treat_max_height_as_none(box) ? input_height : box.computed_values().max_height().to_px(box, height_of_containing_block);
 
     auto min_width = min(specified_min_width, specified_max_width);
     auto max_width = max(specified_min_width, specified_max_width);
@@ -527,8 +527,8 @@ CSSPixels FormattingContext::compute_height_for_replaced_element(Box const& box,
 
     // 2. If this tentative height is greater than 'max-height', the rules above are applied again,
     //    but this time using the value of 'max-height' as the computed value for 'height'.
-    auto computed_max_height = box.computed_values().max_height();
-    if (!computed_max_height.is_none()) {
+    if (!should_treat_max_height_as_none(box)) {
+        auto const& computed_max_height = box.computed_values().max_height();
         if (used_height > computed_max_height.to_px(box, height_of_containing_block)) {
             used_height = tentative_height_for_replaced_element(box, computed_max_height, available_space);
         }
@@ -1655,4 +1655,20 @@ bool box_is_sized_as_replaced_element(Box const& box)
     return is<ReplacedBox>(box) || box.has_preferred_aspect_ratio();
 }
 
+bool FormattingContext::should_treat_max_height_as_none(Box const& box) const
+{
+    // https://www.w3.org/TR/CSS22/visudet.html#min-max-heights
+    // If the height of the containing block is not specified explicitly (i.e., it depends on content height),
+    // and this element is not absolutely positioned, the percentage value is treated as '0' (for 'min-height')
+    // or 'none' (for 'max-height').
+    auto const& max_height = box.computed_values().max_height();
+    if (max_height.is_none())
+        return true;
+    if (box.is_absolutely_positioned())
+        return false;
+    if (max_height.contains_percentage() && !m_state.get(*box.non_anonymous_containing_block()).has_definite_height())
+        return true;
+    return false;
+}
+
 }

+ 2 - 0
Userland/Libraries/LibWeb/Layout/FormattingContext.h

@@ -99,6 +99,8 @@ protected:
     static bool should_treat_width_as_auto(Box const&, AvailableSpace const&);
     static bool should_treat_height_as_auto(Box const&, AvailableSpace const&);
 
+    [[nodiscard]] bool should_treat_max_height_as_none(Box const&) const;
+
     OwnPtr<FormattingContext> layout_inside(Box const&, LayoutMode, AvailableSpace const&);
     void compute_inset(Box const& box);
 

+ 1 - 1
Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp

@@ -186,7 +186,7 @@ void TableFormattingContext::compute_cell_measures(AvailableSpace const& availab
 
         CSSPixels max_height = computed_values.height().is_auto() ? max_content_height : height;
         CSSPixels max_width = computed_values.width().is_auto() ? max_content_width : width;
-        if (!computed_values.max_height().is_none())
+        if (!should_treat_max_height_as_none(cell.box))
             max_height = min(max_height, computed_values.max_height().to_px(cell.box, containing_block.content_height()));
         if (!computed_values.max_width().is_none())
             max_width = min(max_width, computed_values.max_width().to_px(cell.box, containing_block.content_width()));