mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01: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
|
|
@ -0,0 +1,9 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x616 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x600 children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 784x600 children: not-inline
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x616]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x616]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x600]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>) [8,8 784x600]
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
background-color: crimson;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style><div></div>
|
||||||
|
|
@ -600,6 +600,41 @@ CSSPixels BlockFormattingContext::compute_auto_height_for_block_level_element(Bo
|
||||||
return 0;
|
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)
|
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);
|
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);
|
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.
|
// 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()) {
|
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.
|
// 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
|
// 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.
|
// 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()) {
|
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)) {
|
if (independent_formatting_context || !margins_collapse_through(box, m_state)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user