mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Implement "The percentage height calculation quirk" in BFC
See https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk Basically, it means that in quirks mode, percentage height needs to be resolved against nearest ancestor in the containing block chain that does not have height=auto. Fixes https://github.com/LadybirdBrowser/ladybird/issues/365
This commit is contained in:
parent
2e5edcf27e
commit
3a5e78780e
Notes:
github-actions[bot]
2024-09-28 12:42:22 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 3a5e78780e
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1556
3 changed files with 69 additions and 3 deletions
|
@ -600,6 +600,41 @@ CSSPixels BlockFormattingContext::compute_auto_height_for_block_level_element(Bo
|
|||
return 0;
|
||||
}
|
||||
|
||||
static CSSPixels containing_block_height_to_resolve_percentage_in_quirks_mode(Box const& box, LayoutState const& state)
|
||||
{
|
||||
// https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk
|
||||
auto const* containing_block = box.containing_block();
|
||||
while (containing_block) {
|
||||
// 1. Let element be the nearest ancestor containing block of element, if there is one.
|
||||
// Otherwise, return the initial containing block.
|
||||
if (containing_block->is_viewport()) {
|
||||
return state.get(*containing_block).content_height();
|
||||
}
|
||||
|
||||
// 2. If element has a computed value of the display property that is table-cell, then return a
|
||||
// UA-defined value.
|
||||
if (containing_block->display().is_table_cell()) {
|
||||
// FIXME: Likely UA-defined value should not be 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. If element has a computed value of the height property that is not auto, then return element.
|
||||
if (!containing_block->computed_values().height().is_auto()) {
|
||||
return state.get(*containing_block).content_height();
|
||||
}
|
||||
|
||||
// 4. If element has a computed value of the position property that is absolute, or if element is a
|
||||
// not a block container or a table wrapper box, then return element.
|
||||
if (containing_block->is_absolutely_positioned() || !is<BlockContainer>(*containing_block) || is<TableWrapper>(*containing_block)) {
|
||||
return state.get(*containing_block).content_height();
|
||||
}
|
||||
|
||||
// 5. Jump to the first step.
|
||||
containing_block = containing_block->containing_block();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContainer const& block_container, CSSPixels& bottom_of_lowest_margin_box, AvailableSpace const& available_space)
|
||||
{
|
||||
auto& box_state = m_state.get_mutable(box);
|
||||
|
@ -672,11 +707,27 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
|
|||
|
||||
place_block_level_element_in_normal_flow_horizontally(box, available_space);
|
||||
|
||||
resolve_used_height_if_not_treated_as_auto(box, available_space);
|
||||
AvailableSpace available_space_for_height_resolution = available_space;
|
||||
auto is_grid_or_flex_container = box.display().is_grid_inside() || box.display().is_flex_inside();
|
||||
auto is_table_box = box.display().is_table_row() || box.display().is_table_row_group() || box.display().is_table_header_group() || box.display().is_table_footer_group() || box.display().is_table_cell() || box.display().is_table_caption();
|
||||
// NOTE: Spec doesn't mention this but quirk application needs to be skipped for grid and flex containers.
|
||||
// See https://github.com/w3c/csswg-drafts/issues/5545
|
||||
if (box.document().in_quirks_mode() && box.computed_values().height().is_percentage() && !is_table_box && !is_grid_or_flex_container) {
|
||||
// In quirks mode, for the purpose of calculating the height of an element, if the
|
||||
// computed value of the position property of element is relative or static, the specified value
|
||||
// for the height property of element is a <percentage>, and element does not have a computed
|
||||
// value of the display property that is table-row, table-row-group, table-header-group,
|
||||
// table-footer-group, table-cell or table-caption, the containing block of element must be
|
||||
// calculated using the following algorithm, aborting on the first step that returns a value:
|
||||
auto height = containing_block_height_to_resolve_percentage_in_quirks_mode(box, m_state);
|
||||
available_space_for_height_resolution.height = AvailableSize::make_definite(height);
|
||||
}
|
||||
|
||||
resolve_used_height_if_not_treated_as_auto(box, available_space_for_height_resolution);
|
||||
|
||||
// NOTE: Flex containers with `auto` height are treated as `max-content`, so we can compute their height early.
|
||||
if (box.is_replaced_box() || box.display().is_flex_inside()) {
|
||||
resolve_used_height_if_treated_as_auto(box, available_space);
|
||||
resolve_used_height_if_treated_as_auto(box, available_space_for_height_resolution);
|
||||
}
|
||||
|
||||
// Before we insert the children of a list item we need to know the location of the marker.
|
||||
|
@ -726,7 +777,7 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
|
|||
// Tables already set their height during the independent formatting context run. When multi-line text cells are involved, using different
|
||||
// available space here than during the independent formatting context run can result in different line breaks and thus a different height.
|
||||
if (!box.display().is_table_inside()) {
|
||||
resolve_used_height_if_treated_as_auto(box, available_space, independent_formatting_context);
|
||||
resolve_used_height_if_treated_as_auto(box, available_space_for_height_resolution, independent_formatting_context);
|
||||
}
|
||||
|
||||
if (independent_formatting_context || !margins_collapse_through(box, m_state)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue