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

Fixes #19371
This commit is contained in:
Andreas Kling 2023-06-14 15:33:06 +02:00
parent b6f3369b66
commit 43e1343abf
Notes: sideshowbarker 2024-07-17 02:06:40 +09:00
6 changed files with 101 additions and 5 deletions

View file

@ -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>

View file

@ -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>

View file

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

View file

@ -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;
}
}

View file

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

View file

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