diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index c5274ead01..bd577f727d 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -695,6 +695,17 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size( auto clamp_min = has_main_min_size(child_box) ? specified_main_min_size(child_box) : automatic_minimum_size(flex_item); auto clamp_max = has_main_max_size(child_box) ? specified_main_max_size(child_box) : NumericLimits::max(); flex_item.hypothetical_main_size = max(0.0f, css_clamp(flex_item.flex_base_size, clamp_min, clamp_max)); + + // NOTE: At this point, we set the hypothetical main size as the flex item's *temporary* main size. + // The size may change again when we resolve flexible lengths, but this is necessary in order for + // descendants of this flex item to resolve percentage sizes against something. + // + // The spec just barely hand-waves about this, but it seems to *roughly* match what other engines do. + // See "Note" section here: https://drafts.csswg.org/css-flexbox-1/#definite-sizes + if (is_row_layout()) + m_state.get_mutable(flex_item.box).set_temporary_content_width(flex_item.hypothetical_main_size); + else + m_state.get_mutable(flex_item.box).set_temporary_content_height(flex_item.hypothetical_main_size); } // https://drafts.csswg.org/css-flexbox-1/#min-size-auto diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index c82cfd34f6..19131d5dcb 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -301,6 +301,16 @@ void LayoutState::UsedValues::set_content_height(float height) m_has_definite_height = true; } +void LayoutState::UsedValues::set_temporary_content_width(float width) +{ + m_content_width = width; +} + +void LayoutState::UsedValues::set_temporary_content_height(float height) +{ + m_content_height = height; +} + float LayoutState::resolved_definite_width(Box const& box) const { return get(box).content_width(); diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.h b/Userland/Libraries/LibWeb/Layout/LayoutState.h index 9e79c0ce34..a85eae6e5e 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.h +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.h @@ -53,6 +53,11 @@ struct LayoutState { void set_content_width(float); void set_content_height(float); + // NOTE: These are used by FlexFormattingContext to assign a temporary main size to items + // early on, so that descendants have something to resolve percentages against. + void set_temporary_content_width(float); + void set_temporary_content_height(float); + bool has_definite_width() const { return m_has_definite_width && width_constraint == SizeConstraint::None; } bool has_definite_height() const { return m_has_definite_height && height_constraint == SizeConstraint::None; }