Kaynağa Gözat

LibWeb: Do not compensate padding for abspos boxes with static position

When a box does not have a top, left, bottom, or right, there is no
need to adjust the offset for positioning relative to the padding edge,
because the box remains in the normal flow.
Aliaksandr Kalenik 1 yıl önce
ebeveyn
işleme
4164af2ca4

+ 11 - 0
Tests/LibWeb/Layout/expected/block-and-inline/abspos-only-with-inset-left.txt

@@ -0,0 +1,11 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (1,1) content-size 798x330 [BFC] children: not-inline
+    BlockContainer <body> at (10,10) content-size 780x312 children: not-inline
+      BlockContainer <div.box> at (31,21) content-size 200x200 positioned children: not-inline
+        BlockContainer <div.inner> at (12,22) content-size 100x100 positioned [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x332]
+    PaintableWithLines (BlockContainer<BODY>) [9,9 782x314]
+      PaintableWithLines (BlockContainer<DIV>.box) [10,10 272x312]
+        PaintableWithLines (BlockContainer<DIV>.inner) [11,21 102x102]

+ 11 - 0
Tests/LibWeb/Layout/expected/block-and-inline/abspos-with-bottom-right-insets-relative-to-box-with-paddings.txt

@@ -0,0 +1,11 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (1,1) content-size 798x330 [BFC] children: not-inline
+    BlockContainer <body> at (10,10) content-size 780x312 children: not-inline
+      BlockContainer <div.box> at (31,21) content-size 200x200 positioned children: not-inline
+        BlockContainer <div.inner> at (180,220) content-size 100x100 positioned [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x332]
+    PaintableWithLines (BlockContainer<BODY>) [9,9 782x314]
+      PaintableWithLines (BlockContainer<DIV>.box) [10,10 272x312]
+        PaintableWithLines (BlockContainer<DIV>.inner) [179,219 102x102]

+ 11 - 0
Tests/LibWeb/Layout/expected/block-and-inline/abspos-without-insets-relative-top-box-with-padding-top.txt

@@ -0,0 +1,11 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x66 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x50 children: not-inline
+      BlockContainer <div.box> at (8,58) content-size 784x0 positioned children: not-inline
+        BlockContainer <div.inner> at (8,58) content-size 784x50 positioned [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x66] overflow: [0,0 800x108]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x50] overflow: [8,8 784x100]
+      PaintableWithLines (BlockContainer<DIV>.box) [8,8 784x50] overflow: [8,8 784x100]
+        PaintableWithLines (BlockContainer<DIV>.inner) [8,58 784x50]

+ 11 - 0
Tests/LibWeb/Layout/expected/block-and-inline/abspos-without-insets.txt

@@ -0,0 +1,11 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (1,1) content-size 798x330 [BFC] children: not-inline
+    BlockContainer <body> at (10,10) content-size 780x312 children: not-inline
+      BlockContainer <div.box> at (31,21) content-size 200x200 positioned children: not-inline
+        BlockContainer <div.inner> at (32,22) content-size 100x100 positioned [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x332]
+    PaintableWithLines (BlockContainer<BODY>) [9,9 782x314]
+      PaintableWithLines (BlockContainer<DIV>.box) [10,10 272x312]
+        PaintableWithLines (BlockContainer<DIV>.inner) [31,21 102x102]

+ 21 - 0
Tests/LibWeb/Layout/input/block-and-inline/abspos-only-with-inset-left.html

@@ -0,0 +1,21 @@
+<!DOCTYPE html><style>
+* {
+    border: 1px solid black;
+}
+
+.box {
+    position: relative;
+    padding: 10px 50px 100px 20px;
+    background-color: mediumseagreen;
+    width: 200px;
+    height: 200px;
+}
+
+.inner {
+    position: absolute;
+    left: 0;
+    width : 100px;
+    height: 100px;
+    background-color: magenta;
+}
+</style><div class="box"><div class="inner"></div></div>

+ 22 - 0
Tests/LibWeb/Layout/input/block-and-inline/abspos-with-bottom-right-insets-relative-to-box-with-paddings.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html><style>
+* {
+    border: 1px solid black;
+}
+
+.box {
+    position: relative;
+    padding: 10px 50px 100px 20px;
+    background-color: mediumseagreen;
+    width: 200px;
+    height: 200px;
+}
+
+.inner {
+    position: absolute;
+    width : 100px;
+    height: 100px;
+    bottom: 0;
+    right: 0;
+    background-color: magenta;
+}
+</style><div class="box"><div class="inner"></div></div>

+ 15 - 0
Tests/LibWeb/Layout/input/block-and-inline/abspos-without-insets-relative-top-box-with-padding-top.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<style>
+.box {
+  position: relative;
+  padding-top: 50px;
+}
+
+.inner {
+  display: block;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background: linear-gradient(90deg, #FDDE5C 0%, #F8AB5E 16.66667%, #F56A62 33.33333%, #A176C8 50%, #759BEB 66.66667%, #65BEB3 83.33333%, #70DB96);
+}
+</style><div class="box"><div class="inner"></div></div>

+ 20 - 0
Tests/LibWeb/Layout/input/block-and-inline/abspos-without-insets.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html><style>
+* {
+    border: 1px solid black;
+}
+
+.box {
+    position: relative;
+    padding: 10px 50px 100px 20px;
+    background-color: mediumseagreen;
+    width: 200px;
+    height: 200px;
+}
+
+.inner {
+    position: absolute;
+    width : 100px;
+    height: 100px;
+    background-color: magenta;
+}
+</style><div class="box"><div class="inner"></div></div>

+ 6 - 1
Userland/Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -1123,7 +1123,12 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava
     used_offset.set_x(box_state.inset_left + box_state.margin_box_left());
     used_offset.set_y(box_state.inset_top + box_state.margin_box_top());
     // NOTE: Absolutely positioned boxes are relative to the *padding edge* of the containing block.
-    used_offset.translate_by(-containing_block_state.padding_left, -containing_block_state.padding_top);
+    //       Padding offset only need to be compensated when top/left/bottom/right is not auto because otherwise
+    //       the box is positioned at the static position of the containing block.
+    if (!box.computed_values().inset().top().is_auto() || !box.computed_values().inset().bottom().is_auto())
+        used_offset.translate_by(0, -containing_block_state.padding_top);
+    if (!box.computed_values().inset().left().is_auto() || !box.computed_values().inset().right().is_auto())
+        used_offset.translate_by(-containing_block_state.padding_left, 0);
     box_state.set_content_offset(used_offset);
 
     if (independent_formatting_context)