Bug 850684. Make sure offset* is computed correctly on absolutely positioned kids of relatively positioned elements with scrolllframes and borders. r=mats
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 26 Sep 2017 02:01:57 -0400
changeset 670364 8377625a20c16e3fc12513b858e5daf5c306c017
parent 670363 1a063bcbef8a7bd9e6564c5b2c29264163066664
child 670365 50d5710ae6c0ba262a3c8e58ff392005601e352e
push id81612
push userbmo:dharvey@mozilla.com
push dateTue, 26 Sep 2017 10:16:26 +0000
reviewersmats
bugs850684, 81290, 375003
milestone58.0a1
Bug 850684. Make sure offset* is computed correctly on absolutely positioned kids of relatively positioned elements with scrolllframes and borders. r=mats The check for isAbsolutelyPositioned was an old incorrect attempt to fix bug 81290. We have since added the proper fix (not adding offsets of the offset parent frame) in bug 375003. MozReview-Commit-ID: 7NgnfrYcs8h
dom/html/nsGenericHTMLElement.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/cssom-view/offsetTopLeftInScrollableParent.html
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -312,17 +312,17 @@ nsGenericHTMLElement::GetOffsetRect(CSSI
       if (parent->IsAbsPosContainingBlock()) {
         offsetParent = content;
         break;
       }
 
       // Add the parent's origin to our own to get to the
       // right coordinate system.
       const bool isOffsetParent = !isPositioned && IsOffsetParent(parent);
-      if (!isAbsolutelyPositioned && !isOffsetParent) {
+      if (!isOffsetParent) {
         origin += parent->GetPositionIgnoringScrolling();
       }
 
       if (content) {
         // If we've hit the document element, break here.
         if (content == docElement) {
           break;
         }
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -155132,28 +155132,16 @@
       [
        "/css/selectors4/selector-read-write-type-change-002-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
-   "css/selectors4/selector-required.html": [
-    [
-     "/css/selectors4/selector-required.html",
-     [
-      [
-       "/css/selectors4/selector-required-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/selectors4/selector-required-type-change-001.html": [
     [
      "/css/selectors4/selector-required-type-change-001.html",
      [
       [
        "/css/selectors4/selector-required-type-change-001-ref.html",
        "=="
       ]
@@ -155168,16 +155156,28 @@
       [
        "/css/selectors4/selector-required-type-change-002-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
+   "css/selectors4/selector-required.html": [
+    [
+     "/css/selectors4/selector-required.html",
+     [
+      [
+       "/css/selectors4/selector-required-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/selectors4/selectors-dir-selector-ltr-001.html": [
     [
      "/css/selectors4/selectors-dir-selector-ltr-001.html",
      [
       [
        "/css/reference/ref-filled-green-100px-square.xht",
        "=="
       ]
@@ -337716,16 +337716,22 @@
     ]
    ],
    "cssom-view/offsetParent_element_test.html": [
     [
      "/cssom-view/offsetParent_element_test.html",
      {}
     ]
    ],
+   "cssom-view/offsetTopLeftInScrollableParent.html": [
+    [
+     "/cssom-view/offsetTopLeftInScrollableParent.html",
+     {}
+    ]
+   ],
    "cssom-view/scrollIntoView-empty-args.html": [
     [
      "/cssom-view/scrollIntoView-empty-args.html",
      {}
     ]
    ],
    "cssom-view/scrollIntoView-shadow.html": [
     [
@@ -548962,74 +548968,74 @@
    "59f848418882c75898c422a9600c14ffab64c3d9",
    "support"
   ],
   "css/selectors4/of-type-selectors.xhtml": [
    "607553f41a33ce3630752cdf027c9f904833a19d",
    "reftest"
   ],
   "css/selectors4/selector-placeholder-shown-type-change-001-ref.html": [
-    "92303d06943581738f58ff5d342ef1336539f66a",
-    "support"
+   "92303d06943581738f58ff5d342ef1336539f66a",
+   "support"
+  ],
+  "css/selectors4/selector-placeholder-shown-type-change-001.html": [
+   "afb7a260d6f1c7da337a1f20a62778d1d6e302c4",
+   "reftest"
   ],
   "css/selectors4/selector-placeholder-shown-type-change-002-ref.html": [
-    "ac3a88a758fd0ccc67077993d59bfb34eadf3931",
-    "support"
-  ],
-  "css/selectors4/selector-placeholder-shown-type-change-003-ref.html": [
-    "ac3a88a758fd0ccc67077993d59bfb34eadf3931",
-    "support"
-  ],
-  "css/selectors4/selector-placeholder-shown-type-change-001.html": [
-    "afb7a260d6f1c7da337a1f20a62778d1d6e302c4",
-    "reftest"
+   "ac3a88a758fd0ccc67077993d59bfb34eadf3931",
+   "support"
   ],
   "css/selectors4/selector-placeholder-shown-type-change-002.html": [
-    "df0cbd1b178d72de9f70d0e603c30858508c2edd",
-    "reftest"
+   "a0872a296c81ab57649c963304269c7f38e7e4b7",
+   "reftest"
+  ],
+  "css/selectors4/selector-placeholder-shown-type-change-003-ref.html": [
+   "ac3a88a758fd0ccc67077993d59bfb34eadf3931",
+   "support"
   ],
   "css/selectors4/selector-placeholder-shown-type-change-003.html": [
-    "36046107e0f3763e219a2316ab6232785a325257",
-    "reftest"
+   "37ba577eeb816bec60a2ee44569001b1a6f76bcf",
+   "reftest"
   ],
   "css/selectors4/selector-read-write-type-change-001-ref.html": [
-    "812f07e03f5bbf86feb2d8eefe17aeaa7bd69970",
-    "support"
+   "812f07e03f5bbf86feb2d8eefe17aeaa7bd69970",
+   "support"
   ],
   "css/selectors4/selector-read-write-type-change-001.html": [
-    "95da0fbd6aafb8dcecb6f39e5cc8572f536e7eb5",
-    "reftest"
+   "95da0fbd6aafb8dcecb6f39e5cc8572f536e7eb5",
+   "reftest"
   ],
   "css/selectors4/selector-read-write-type-change-002-ref.html": [
-    "3579aa13253d99a430ce17ba1acd629a22261097",
-    "support"
+   "3579aa13253d99a430ce17ba1acd629a22261097",
+   "support"
   ],
   "css/selectors4/selector-read-write-type-change-002.html": [
-    "0bb1111fd76582a433204bce32852fc0a5dc5458",
-    "reftest"
+   "0bb1111fd76582a433204bce32852fc0a5dc5458",
+   "reftest"
   ],
   "css/selectors4/selector-required-ref.html": [
    "815bc765614b4c2e3d8f8f6303e6bb2ee0989c23",
    "support"
   ],
   "css/selectors4/selector-required-type-change-001-ref.html": [
-    "812f07e03f5bbf86feb2d8eefe17aeaa7bd69970",
-    "support"
+   "812f07e03f5bbf86feb2d8eefe17aeaa7bd69970",
+   "support"
   ],
   "css/selectors4/selector-required-type-change-001.html": [
-    "211b7b71cf1073dd15491b78b0152f9b7a5e9aec",
-    "reftest"
+   "211b7b71cf1073dd15491b78b0152f9b7a5e9aec",
+   "reftest"
   ],
   "css/selectors4/selector-required-type-change-002-ref.html": [
-    "3579aa13253d99a430ce17ba1acd629a22261097",
-    "support"
+   "3579aa13253d99a430ce17ba1acd629a22261097",
+   "support"
   ],
   "css/selectors4/selector-required-type-change-002.html": [
-    "f27dbc7bd1e2aa0753bcae73fdf2d83f7248118a",
-    "reftest"
+   "f27dbc7bd1e2aa0753bcae73fdf2d83f7248118a",
+   "reftest"
   ],
   "css/selectors4/selector-required.html": [
    "601b8b8426c64717f82831e6258f8fe4188c797c",
    "reftest"
   ],
   "css/selectors4/selectors-dir-selector-ltr-001.html": [
    "3682f8a499ad2a1348f620b33b83944c0dc90788",
    "reftest"
@@ -578653,16 +578659,20 @@
   "cssom-view/negativeMargins.html": [
    "ad44e3f4ba132bfb4a522b14a4ff5356dbbbad14",
    "testharness"
   ],
   "cssom-view/offsetParent_element_test.html": [
    "b2261ec702116c211ab5ac6fbb53698dfe60a7be",
    "testharness"
   ],
+  "cssom-view/offsetTopLeftInScrollableParent.html": [
+   "79b4a278f0e35646cfdffeebf8f0523e2772bc9b",
+   "testharness"
+  ],
   "cssom-view/resources/elementsFromPoint.js": [
    "0c31158817d4d6f9e59df0d2ebe0e41c6ce41bb5",
    "support"
   ],
   "cssom-view/resources/iframe1.html": [
    "ec93f617bdc7b0055d96c7b00ab7832cca1c1af0",
    "support"
   ],
@@ -624014,17 +624024,17 @@
    "4db5bfbf0f1afcace2a4ea79451c2ff5fc09ab3c",
    "testharness"
   ],
   "service-workers/service-worker/postmessage.https.html": [
    "ea380417fcad1583f764473c554bf519e5beecde",
    "testharness"
   ],
   "service-workers/service-worker/ready.https.html": [
-   "ff14496607e396281d28fb9a8bfdcbb46b8a7e9c",
+   "1f479de232c8e847fcaa31bb5ed869fe070054b6",
    "testharness"
   ],
   "service-workers/service-worker/redirected-response.https.html": [
    "38b406b1d9fd32296a72b264e2d7ccb0effed619",
    "testharness"
   ],
   "service-workers/service-worker/referer.https.html": [
    "a9e4073192f5b69984624ad7376ec7787101dfea",
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/cssom-view/offsetTopLeftInScrollableParent.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id="parent" style="overflow:scroll; height: 100px; position: relative">
+  <div id="spacer" style="height: 200px"></div>
+  <div id="child"></div>
+  <div id="absolute-child" style="position: absolute; top: 41px; left: 43px"></div>
+</div>
+<script>
+test(function() {
+    var child = document.getElementById("child");
+    assert_equals(child.offsetTop, 200, "Child is after spacer");
+    assert_equals(child.offsetLeft, 0, "Child is flush left");
+    var absChild = document.getElementById("absolute-child");
+    assert_equals(absChild.offsetTop, 41, "Abspos child is y-positioned");
+    assert_equals(absChild.offsetLeft, 43, "Abspos child is x-positioned");
+}, "Basic functionality");
+
+test(function() {
+    var parent = document.getElementById("parent");
+    parent.scrollTop = 100;
+    var child = document.getElementById("child");
+    assert_equals(child.offsetTop, 200, "Child is after spacer");
+    assert_equals(child.offsetLeft, 0, "Child is flush left");
+    var absChild = document.getElementById("absolute-child");
+    assert_equals(absChild.offsetTop, 41, "Abspos child is y-positioned");
+    assert_equals(absChild.offsetLeft, 43, "Abspos child is x-positioned");
+}, "Basic functionality in scrolled parent");
+
+test(function() {
+    var child = document.getElementById("child");
+    child.style.marginTop = "20px"
+    child.style.marginLeft = "100px";
+    assert_equals(child.offsetTop, 220, "Child is after spacer and margin");
+    assert_equals(child.offsetLeft, 100, "Child is 100px from left");
+    var absChild = document.getElementById("absolute-child");
+    absChild.style.marginTop = "20px"
+    absChild.style.marginLeft = "100px";
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child");
+
+test(function() {
+    var parent = document.getElementById("parent");
+    parent.style.marginTop = "66px"
+    parent.style.marginLeft = "33px";
+    var child = document.getElementById("child");
+    assert_equals(child.offsetTop, 220, "Child is after spacer and margin");
+    assert_equals(child.offsetLeft, 100, "Child is 100px from left");
+    var absChild = document.getElementById("absolute-child");
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child and parent");
+
+test(function() {
+    var child = document.getElementById("child");
+    child.style.borderTop = "13px solid green";
+    child.style.borderLeft = "7px solid green";
+    assert_equals(child.offsetTop, 220, "Child is after spacer and margin");
+    assert_equals(child.offsetLeft, 100, "Child is 100px from left");
+    var absChild = document.getElementById("absolute-child");
+    absChild.style.borderTop = "13px solid green";
+    absChild.style.borderLeft = "7px solid green";
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child and parent, border on child");
+
+test(function() {
+    var parent = document.getElementById("parent");
+    parent.style.borderTop = "23px solid yellow";
+    parent.style.borderLeft = "19px solid yellow";
+    var child = document.getElementById("child");
+    assert_equals(child.offsetTop, 220, "Child is after spacer and margin");
+    assert_equals(child.offsetLeft, 100, "Child is 100px from left");
+    var absChild = document.getElementById("absolute-child");
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child and parent, border on child and parent");
+
+
+test(function() {
+    var child = document.getElementById("child");
+    child.style.paddingTop = "31px";
+    child.style.paddingLeft = "37px";
+    assert_equals(child.offsetTop, 220, "Child is after spacer and margin");
+    assert_equals(child.offsetLeft, 100, "Child is 100px from left");
+    var absChild = document.getElementById("absolute-child");
+    absChild.style.paddingTop = "31px";
+    absChild.style.paddingLeft = "37px";
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child and parent, border on child and parent, padding on child");
+
+
+test(function() {
+    var parent = document.getElementById("parent");
+    parent.style.paddingTop = "31px";
+    parent.style.paddingLeft = "37px";
+    var child = document.getElementById("child");
+    assert_equals(child.offsetTop, 251, "Child is after spacer and margin and parent padding");
+    assert_equals(child.offsetLeft, 137, "Child is 100px + parent padding from left");
+    var absChild = document.getElementById("absolute-child");
+    // Padding on the parent does not affect the position of the absolute containing block.
+    assert_equals(absChild.offsetTop, 61, "Abspos child is y-positioned and has margin");
+    assert_equals(absChild.offsetLeft, 143, "Abspos child is x-positioned and has margin");
+}, "Margins on child and parent, border on child and parent, padding on child and parent");
+
+</script>