ソースを参照

LibWeb: Ignore flex container size constraints during intrinsic sizing

Properties like min-width, max-width, etc, should be ignored while we're
trying to determine the intrinsic size of a flex container.

This fixes an infinite recursion when using an intrinsic size keyword as
the max-width of a flex column container.

Note that this behavior is marked as AD-HOC in code comments because
specs don't tell us how to achieve intrinsic sizing.

We can now load product pages on the Twinings site, such as
https://twinings.co.uk/products/earl-grey-100-tea-bags :^)
Andreas Kling 1 年間 前
コミット
15440b156f

+ 3 - 0
Tests/LibWeb/Layout/expected/flex/flex-column-container-with-max-width-max-content.txt

@@ -0,0 +1,3 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x16 [BFC] children: not-inline
+    Box <body> at (8,8) content-size 0x0 flex-container(column) [FFC] children: not-inline

+ 7 - 0
Tests/LibWeb/Layout/input/flex/flex-column-container-with-max-width-max-content.html

@@ -0,0 +1,7 @@
+<!doctype html><style>
+    body {
+        display: flex;
+        flex-direction: column;
+        max-width: max-content;
+    }
+</style>

+ 13 - 6
Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp

@@ -1214,7 +1214,8 @@ void FlexFormattingContext::calculate_cross_size_of_each_flex_line()
 
     // If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes.
     // Note that if CSS 2.1’s definition of min/max-width/height applied more generally, this behavior would fall out automatically.
-    if (is_single_line()) {
+    // AD-HOC: We don't do this when the flex container is being sized under a min-content or max-content constraint.
+    if (is_single_line() && !m_available_space_for_flex_container->cross.is_intrinsic_sizing_constraint()) {
         auto const& computed_min_size = this->computed_cross_min_size(flex_container());
         auto const& computed_max_size = this->computed_cross_max_size(flex_container());
         auto cross_min_size = (!computed_min_size.is_auto() && !computed_min_size.contains_percentage()) ? specified_cross_min_size(flex_container()) : 0;
@@ -1530,11 +1531,17 @@ void FlexFormattingContext::determine_flex_container_used_cross_size()
             cross_size = cross_size_value.to_px(flex_container(), inner_cross_size(*flex_container().containing_block()));
         }
     }
-    auto const& computed_min_size = this->computed_cross_min_size(flex_container());
-    auto const& computed_max_size = this->computed_cross_max_size(flex_container());
-    auto cross_min_size = (!computed_min_size.is_auto() && !computed_min_size.contains_percentage()) ? specified_cross_min_size(flex_container()) : 0;
-    auto cross_max_size = (!computed_max_size.is_none() && !computed_max_size.contains_percentage()) ? specified_cross_max_size(flex_container()) : INFINITY;
-    set_cross_size(flex_container(), css_clamp(cross_size, cross_min_size, cross_max_size));
+
+    // AD-HOC: We don't apply min/max cross size constraints when sizing the flex container under an intrinsic sizing constraint.
+    if (!m_available_space_for_flex_container->cross.is_intrinsic_sizing_constraint()) {
+        auto const& computed_min_size = this->computed_cross_min_size(flex_container());
+        auto const& computed_max_size = this->computed_cross_max_size(flex_container());
+        auto cross_min_size = (!computed_min_size.is_auto() && !computed_min_size.contains_percentage()) ? specified_cross_min_size(flex_container()) : 0;
+        auto cross_max_size = (!computed_max_size.is_none() && !computed_max_size.contains_percentage()) ? specified_cross_max_size(flex_container()) : INFINITY;
+        set_cross_size(flex_container(), css_clamp(cross_size, cross_min_size, cross_max_size));
+    } else {
+        set_cross_size(flex_container(), cross_size);
+    }
 }
 
 // https://www.w3.org/TR/css-flexbox-1/#algo-line-align