Pārlūkot izejas kodu

LibWeb: Don't allow resolved height of abspos elements to become negative

We have to clamp the resulting height to 0 when solving for it.
Andreas Kling 2 gadi atpakaļ
vecāks
revīzija
4bf10674fa

+ 5 - 0
Tests/LibWeb/Layout/expected/automatic-height-of-non-replaced-abspos-element-must-not-be-negative.txt

@@ -0,0 +1,5 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x0 children: not-inline
+    BlockContainer <body.outer> at (8,8) content-size 0x0 positioned children: not-inline
+      BlockContainer <div.inner> at (9,9) content-size 0x0 positioned children: inline
+        TextNode <#text>

+ 11 - 0
Tests/LibWeb/Layout/input/automatic-height-of-non-replaced-abspos-element-must-not-be-negative.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html><html><head><style>
+    .outer {
+        position: absolute;
+    }
+    .inner {
+        position: absolute;
+        top: 0;
+        bottom: 0;
+        border: 1px solid black;
+    }
+</style></head><body class="outer"><div class="inner">

+ 11 - 5
Userland/Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -660,9 +660,12 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
     auto height_of_containing_block = available_space.height.to_px();
     auto height_of_containing_block_as_length = CSS::Length::make_px(height_of_containing_block);
 
-    auto solve_for = [&](CSS::Length length) {
-        return CSS::Length::make_px(
-            height_of_containing_block
+    enum class ClampToZero {
+        No,
+        Yes,
+    };
+    auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) {
+        auto unclamped_value = height_of_containing_block
             - top.resolved(box, height_of_containing_block_as_length).to_px(box)
             - margin_top.resolved(box, width_of_containing_block_as_length).to_px(box)
             - box.computed_values().border_top().width
@@ -672,7 +675,10 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
             - box.computed_values().border_bottom().width
             - margin_bottom.resolved(box, width_of_containing_block_as_length).to_px(box)
             - bottom.resolved(box, height_of_containing_block_as_length).to_px(box)
-            + length.to_px(box));
+            + length.to_px(box);
+        if (clamp_to_zero == ClampToZero::Yes)
+            return CSS::Length::make_px(max(CSSPixels(0), unclamped_value));
+        return CSS::Length::make_px(unclamped_value);
     };
 
     auto solve_for_top = [&] {
@@ -684,7 +690,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
     };
 
     auto solve_for_height = [&] {
-        height = CSS::Size::make_length(solve_for(height.resolved(box, height_of_containing_block_as_length)));
+        height = CSS::Size::make_length(solve_for(height.resolved(box, height_of_containing_block_as_length), ClampToZero::Yes));
     };
 
     auto solve_for_margin_top = [&] {