at (8,8) content-size 784x300 children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+ PaintableWithLines (BlockContainer) [0,0 800x600]
+ PaintableWithLines (BlockContainer) [8,8 784x300]
+ PaintableWithLines (BlockContainer
) [8,8 784x300]
diff --git a/Tests/LibWeb/Layout/input/block-and-inline/percentage-height-box-nested-into-percentage-height-box.html b/Tests/LibWeb/Layout/input/block-and-inline/percentage-height-box-nested-into-percentage-height-box.html
new file mode 100644
index 00000000000..d2a6e604f7c
--- /dev/null
+++ b/Tests/LibWeb/Layout/input/block-and-inline/percentage-height-box-nested-into-percentage-height-box.html
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
index a9b8c0c65d1..85dafe1d8f4 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
@@ -407,24 +407,48 @@ void BlockFormattingContext::compute_width_for_block_level_replaced_element_in_n
box_state.padding_right = padding_right;
}
-void BlockFormattingContext::compute_height(Box const& box, AvailableSpace const& available_space, FormattingContext const* box_formatting_context)
+void BlockFormattingContext::resolve_used_height_if_not_treated_as_auto(Box const& box, AvailableSpace const& available_space)
{
- auto const& computed_values = box.computed_values();
- auto& box_used_values = m_state.get_mutable(box);
+ if (should_treat_height_as_auto(box, available_space)) {
+ return;
+ }
+
+ auto const& computed_values = box.computed_values();
+ auto& box_state = m_state.get_mutable(box);
+
+ auto height = calculate_inner_height(box, available_space.height, box.computed_values().height());
+
+ if (!should_treat_max_height_as_none(box, available_space.height)) {
+ if (!computed_values.max_height().is_auto()) {
+ auto max_height = calculate_inner_height(box, available_space.height, computed_values.max_height());
+ height = min(height, max_height);
+ }
+ }
+ if (!computed_values.min_height().is_auto()) {
+ height = max(height, calculate_inner_height(box, available_space.height, computed_values.min_height()));
+ }
+
+ box_state.set_content_height(height);
+ box_state.set_has_definite_height(true);
+}
+
+void BlockFormattingContext::resolve_used_height_if_treated_as_auto(Box const& box, AvailableSpace const& available_space, FormattingContext const* box_formatting_context)
+{
+ if (!should_treat_height_as_auto(box, available_space)) {
+ return;
+ }
+
+ auto const& computed_values = box.computed_values();
+ auto& box_state = m_state.get_mutable(box);
- // Then work out what the height is, based on box type and CSS properties.
CSSPixels height = 0;
if (box_is_sized_as_replaced_element(box)) {
height = compute_height_for_replaced_element(box, available_space);
} else {
- if (should_treat_height_as_auto(box, available_space)) {
- if (box_formatting_context) {
- height = box_formatting_context->automatic_content_height();
- } else {
- height = compute_auto_height_for_block_level_element(box, m_state.get(box).available_inner_space_or_constraints_from(available_space));
- }
+ if (box_formatting_context) {
+ height = box_formatting_context->automatic_content_height();
} else {
- height = calculate_inner_height(box, available_space.height, computed_values.height());
+ height = compute_auto_height_for_block_level_element(box, m_state.get(box).available_inner_space_or_constraints_from(available_space));
}
}
@@ -446,8 +470,6 @@ void BlockFormattingContext::compute_height(Box const& box, AvailableSpace const
// https://quirks.spec.whatwg.org/#the-html-element-fills-the-viewport-quirk
// FIXME: Handle vertical writing mode.
- auto& box_state = m_state.get_mutable(box);
-
// 1. Let margins be sum of the used values of the margin-left and margin-right properties of element
// if element has a vertical writing mode, otherwise let margins be the sum of the used values of
// the margin-top and margin-bottom properties of element.
@@ -461,10 +483,10 @@ void BlockFormattingContext::compute_height(Box const& box, AvailableSpace const
height = max(size, height);
// NOTE: The height of the root element when affected by this quirk is considered to be definite.
- box_used_values.set_has_definite_height(true);
+ box_state.set_has_definite_height(true);
}
- box_used_values.set_content_height(height);
+ box_state.set_content_height(height);
}
void BlockFormattingContext::layout_inline_children(BlockContainer const& block_container, AvailableSpace const& available_space)
@@ -616,7 +638,7 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
// NOTE: In quirks mode, the html element's height matches the viewport so it can be treated as definite
if (box_state.has_definite_height() || box_is_html_element_in_quirks_mode) {
- compute_height(box, available_space);
+ resolve_used_height_if_treated_as_auto(box, available_space);
}
auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, m_layout_mode, box);
@@ -650,9 +672,12 @@ 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);
+
// 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())
- compute_height(box, available_space);
+ if (box.is_replaced_box() || box.display().is_flex_inside()) {
+ resolve_used_height_if_treated_as_auto(box, available_space);
+ }
// Before we insert the children of a list item we need to know the location of the marker.
// If we do not do this then left-floating elements inside the list item will push the marker to the right,
@@ -701,7 +726,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()) {
- compute_height(box, available_space, independent_formatting_context);
+ resolve_used_height_if_treated_as_auto(box, available_space, independent_formatting_context);
}
if (independent_formatting_context || !margins_collapse_through(box, m_state)) {
@@ -939,12 +964,15 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
compute_width(box, available_space);
+ resolve_used_height_if_not_treated_as_auto(box, available_space);
+
// 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())
- compute_height(box, available_space);
+ if (box.is_replaced_box() || box.display().is_flex_inside()) {
+ resolve_used_height_if_treated_as_auto(box, available_space);
+ }
auto independent_formatting_context = layout_inside(box, m_layout_mode, box_state.available_inner_space_or_constraints_from(available_space));
- compute_height(box, available_space, independent_formatting_context);
+ resolve_used_height_if_treated_as_auto(box, available_space, independent_formatting_context);
// First we place the box normally (to get the right y coordinate.)
// If we have a LineBuilder, we're in the middle of inline layout, otherwise this is block layout.
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
index aae4039046f..06985760213 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
@@ -37,7 +37,8 @@ public:
virtual void parent_context_did_dimension_child_root_box() override;
- void compute_height(Box const&, AvailableSpace const&, FormattingContext const* box_formatting_context = nullptr);
+ void resolve_used_height_if_not_treated_as_auto(Box const&, AvailableSpace const&);
+ void resolve_used_height_if_treated_as_auto(Box const&, AvailableSpace const&, FormattingContext const* box_formatting_context = nullptr);
SpaceUsedAndContainingMarginForFloats space_used_and_containing_margin_for_floats(CSSPixels y) const;
[[nodiscard]] SpaceUsedByFloats intrusion_by_floats_into_box(Box const&, CSSPixels y_in_box) const;
diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
index 374954ee5bc..2d3400d6733 100644
--- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
@@ -177,16 +177,18 @@ void InlineFormattingContext::dimension_box_on_line(Box const& box, LayoutMode l
box_state.set_content_width(width);
+ parent().resolve_used_height_if_not_treated_as_auto(box, AvailableSpace(AvailableSize::make_definite(width), AvailableSize::make_indefinite()));
+
// NOTE: Flex containers with `auto` height are treated as `max-content`, so we can compute their height early.
if (box_state.has_definite_height() || box.display().is_flex_inside())
- parent().compute_height(box, AvailableSpace(AvailableSize::make_definite(width), AvailableSize::make_indefinite()));
+ parent().resolve_used_height_if_treated_as_auto(box, AvailableSpace(AvailableSize::make_definite(width), AvailableSize::make_indefinite()));
auto independent_formatting_context = layout_inside(box, layout_mode, box_state.available_inner_space_or_constraints_from(*m_available_space));
auto const& height_value = box.computed_values().height();
if (should_treat_height_as_auto(box, *m_available_space)) {
// FIXME: (10.6.6) If 'height' is 'auto', the height depends on the element's descendants per 10.6.7.
- parent().compute_height(box, AvailableSpace(AvailableSize::make_indefinite(), AvailableSize::make_indefinite()));
+ parent().resolve_used_height_if_treated_as_auto(box, AvailableSpace(AvailableSize::make_indefinite(), AvailableSize::make_indefinite()));
} else {
auto inner_height = calculate_inner_height(box, AvailableSize::make_definite(m_containing_block_used_values.content_height()), height_value);
box_state.set_content_height(inner_height);