From 43e1343abffba54711e6debc6943676a7871d2ae Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 14 Jun 2023 15:33:06 +0200 Subject: [PATCH] LibWeb: Treat % max-height as none when containing block size indefinite Fixes #19371 --- ...containing-block-has-indefinite-height.txt | 46 +++++++++++++++++++ ...ontaining-block-has-indefinite-height.html | 32 +++++++++++++ .../LibWeb/Layout/BlockFormattingContext.cpp | 2 +- .../LibWeb/Layout/FormattingContext.cpp | 22 +++++++-- .../LibWeb/Layout/FormattingContext.h | 2 + .../LibWeb/Layout/TableFormattingContext.cpp | 2 +- 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/percentage-max-height-when-containing-block-has-indefinite-height.txt create mode 100644 Tests/LibWeb/Layout/input/percentage-max-height-when-containing-block-has-indefinite-height.html diff --git a/Tests/LibWeb/Layout/expected/percentage-max-height-when-containing-block-has-indefinite-height.txt b/Tests/LibWeb/Layout/expected/percentage-max-height-when-containing-block-has-indefinite-height.txt new file mode 100644 index 00000000000..3f34ad1011d --- /dev/null +++ b/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 at (1,1) content-size 798x123.34375 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x105.34375 children: not-inline + BlockContainer at (11,11) content-size 778x19.46875 [BFC] children: not-inline + BlockContainer
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 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
+ TextNode <#text> + BlockContainer <(anonymous)> at (10,50.9375) content-size 780x0 children: inline + TextNode <#text> + Box at (11,51.9375) content-size 778x19.46875 flex-container(row) [FFC] children: not-inline + BlockContainer
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 at (11,73.40625) content-size 778x19.46875 [GFC] children: not-inline + BlockContainer
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 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
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> diff --git a/Tests/LibWeb/Layout/input/percentage-max-height-when-containing-block-has-indefinite-height.html b/Tests/LibWeb/Layout/input/percentage-max-height-when-containing-block-has-indefinite-height.html new file mode 100644 index 00000000000..e33c4445d6b --- /dev/null +++ b/Tests/LibWeb/Layout/input/percentage-max-height-when-containing-block-has-indefinite-height.html @@ -0,0 +1,32 @@ + +
block
+
inline
+
flex
+
grid
+
table
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index ce612d16cfb..57d230a7d56 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/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)); diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 3993412ecfc..c11a7830605 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/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(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; +} + } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index 3a0db1a3bb3..fc5f3fb65a4 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/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 layout_inside(Box const&, LayoutMode, AvailableSpace const&); void compute_inset(Box const& box); diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp index fa930809130..9d7a0d4a639 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/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()));