diff --git a/Base/res/html/tests/abspos-flexbox-with-auto-height.html b/Base/res/html/tests/abspos-flexbox-with-auto-height.html
new file mode 100644
index 0000000000..0eb5ce9ce3
--- /dev/null
+++ b/Base/res/html/tests/abspos-flexbox-with-auto-height.html
@@ -0,0 +1,12 @@
+
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
index 61b8a0fcf0..b735980240 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
@@ -386,12 +386,12 @@ void FormattingContext::compute_width_for_absolutely_positioned_element(Box cons
compute_width_for_absolutely_positioned_non_replaced_element(box, available_space);
}
-void FormattingContext::compute_height_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space)
+void FormattingContext::compute_height_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout before_or_after_inside_layout)
{
if (is(box))
- compute_height_for_absolutely_positioned_replaced_element(static_cast(box), available_space);
+ compute_height_for_absolutely_positioned_replaced_element(static_cast(box), available_space, before_or_after_inside_layout);
else
- compute_height_for_absolutely_positioned_non_replaced_element(box, available_space);
+ compute_height_for_absolutely_positioned_non_replaced_element(box, available_space, before_or_after_inside_layout);
}
CSSPixels FormattingContext::compute_width_for_replaced_element(LayoutState const& state, ReplacedBox const& box, AvailableSpace const& available_space)
@@ -636,13 +636,17 @@ void FormattingContext::compute_width_for_absolutely_positioned_replaced_element
}
// https://drafts.csswg.org/css-position-3/#abs-non-replaced-height
-void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_element(Box const& box, AvailableSpace const& available_space)
+void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_element(Box const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout before_or_after_inside_layout)
{
// 5.3. The Height Of Absolutely Positioned, Non-Replaced Elements
// For absolutely positioned elements, the used values of the vertical dimensions must satisfy this constraint:
// top + margin-top + border-top-width + padding-top + height + padding-bottom + border-bottom-width + margin-bottom + bottom = height of containing block
+ // NOTE: This function is called twice: both before and after inside layout.
+ // In the before pass, if it turns out we need the automatic height of the box, we abort these steps.
+ // This allows the box to retain an indefinite height from the perspective of inside layout.
+
auto margin_top = box.computed_values().margin().top();
auto margin_bottom = box.computed_values().margin().bottom();
auto top = box.computed_values().inset().top();
@@ -697,6 +701,10 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
// If all three of top, height, and bottom are auto:
if (top.is_auto() && height.is_auto() && bottom.is_auto()) {
+ // (If we haven't done inside layout yet, we can't compute the auto height.)
+ if (before_or_after_inside_layout == BeforeOrAfterInsideLayout::Before)
+ return;
+
// First set any auto values for margin-top and margin-bottom to 0,
if (margin_top.is_auto())
margin_top = CSS::Length::make_px(0);
@@ -748,6 +756,10 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
// 1. If top and height are auto and bottom is not auto,
if (top.is_auto() && height.is_auto() && !bottom.is_auto()) {
+ // (If we haven't done inside layout yet, we can't compute the auto height.)
+ if (before_or_after_inside_layout == BeforeOrAfterInsideLayout::Before)
+ return;
+
// then the height is based on the Auto heights for block formatting context roots,
height = CSS::Size::make_px(compute_auto_height_for_block_formatting_context_root(verify_cast(box)));
@@ -766,6 +778,10 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
// 3. If height and bottom are auto and top is not auto,
else if (height.is_auto() && bottom.is_auto() && !top.is_auto()) {
+ // (If we haven't done inside layout yet, we can't compute the auto height.)
+ if (before_or_after_inside_layout == BeforeOrAfterInsideLayout::Before)
+ return;
+
// then the height is based on the Auto heights for block formatting context roots,
height = CSS::Size::make_px(compute_auto_height_for_block_formatting_context_root(verify_cast(box)));
@@ -893,10 +909,11 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava
// NOTE: We compute height before *and* after doing inside layout.
// This is done so that inside layout can resolve percentage heights.
// In some situations, e.g with non-auto top & bottom values, the height can be determined early.
- compute_height_for_absolutely_positioned_element(box, available_space);
+ compute_height_for_absolutely_positioned_element(box, available_space, BeforeOrAfterInsideLayout::Before);
auto independent_formatting_context = layout_inside(box, LayoutMode::Normal, box_state.available_inner_space_or_constraints_from(available_space));
- compute_height_for_absolutely_positioned_element(box, available_space);
+
+ compute_height_for_absolutely_positioned_element(box, available_space, BeforeOrAfterInsideLayout::After);
box_state.margin_left = box.computed_values().margin().left().resolved(box, width_of_containing_block_as_length).to_px(box);
box_state.margin_top = box.computed_values().margin().top().resolved(box, width_of_containing_block_as_length).to_px(box);
@@ -966,7 +983,7 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava
independent_formatting_context->parent_context_did_dimension_child_root_box();
}
-void FormattingContext::compute_height_for_absolutely_positioned_replaced_element(ReplacedBox const& box, AvailableSpace const& available_space)
+void FormattingContext::compute_height_for_absolutely_positioned_replaced_element(ReplacedBox const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout)
{
// 10.6.5 Absolutely positioned, replaced elements
// The used value of 'height' is determined as for inline replaced elements.
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
index 1b74d88650..7e1692c8e0 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
@@ -110,9 +110,14 @@ protected:
void compute_width_for_absolutely_positioned_element(Box const&, AvailableSpace const&);
void compute_width_for_absolutely_positioned_non_replaced_element(Box const&, AvailableSpace const&);
void compute_width_for_absolutely_positioned_replaced_element(ReplacedBox const&, AvailableSpace const&);
- void compute_height_for_absolutely_positioned_element(Box const&, AvailableSpace const&);
- void compute_height_for_absolutely_positioned_non_replaced_element(Box const&, AvailableSpace const&);
- void compute_height_for_absolutely_positioned_replaced_element(ReplacedBox const&, AvailableSpace const&);
+
+ enum class BeforeOrAfterInsideLayout {
+ Before,
+ After,
+ };
+ void compute_height_for_absolutely_positioned_element(Box const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
+ void compute_height_for_absolutely_positioned_non_replaced_element(Box const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
+ void compute_height_for_absolutely_positioned_replaced_element(ReplacedBox const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
Type m_type {};