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 @@
+
+
+
+
+
+
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()));