commit 6da49d548d3373b95591b968e764f405a1535e0d
parent 6159ff26750c145723217199b0d8efb4b1a0985d
Author: David Shin <dshin@mozilla.com>
Date: Mon, 15 Dec 2025 16:18:55 +0000
Bug 2006097: Unscroll position-area modified containing block. r=layout-anchor-positioning-reviewers,layout-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D276467
Diffstat:
3 files changed, 177 insertions(+), 7 deletions(-)
diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp
@@ -1251,9 +1251,12 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame(
aKidFrame->GetWritingMode(),
aDelegatingFrame->GetWritingMode(), positionArea,
&resolvedPositionArea);
- return ContainingBlockRect{offset, resolvedPositionArea,
- aOriginalScrollableContainingBlockRect,
- scrolledAnchorCb};
+ return ContainingBlockRect{
+ offset, resolvedPositionArea,
+ aOriginalScrollableContainingBlockRect,
+ // Unscroll the CB by canceling out the previously applied
+ // scroll offset (See above), the offset will be applied later.
+ scrolledAnchorCb + offset};
}
return ContainingBlockRect{aOriginalScrollableContainingBlockRect};
}
@@ -1519,10 +1522,6 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame(
// block, which is necessary for inset computation. However, the position
// of a frame originates against the border box.
r += cb.mFinalRect.TopLeft();
- if (cb.mAnchorShiftInfo) {
- // Push the frame out to where the anchor is.
- r += cb.mAnchorShiftInfo->mOffset;
- }
aKidFrame->SetRect(r);
}
diff --git a/testing/web-platform/tests/css/css-anchor-position/position-area-anchor-002-ref.html b/testing/web-platform/tests/css/css-anchor-position/position-area-anchor-002-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>anchor() resolution in position-area</title>
+<style>
+.abs-cb {
+ width: 180px;
+ height: 180px;
+ position: relative;
+ border: 5px solid;
+}
+
+.scroller {
+ width: 100%;
+ height: 100%;
+ overflow: scroll;
+}
+
+.anchor {
+ width: 60px;
+ height: 60px;
+ margin-left: 60px;
+ background: pink;
+}
+
+.filler {
+ width: 1px;
+ height: 180px;
+}
+
+.positioned {
+ width: 30px;
+ height: 30px;
+ background: purple;
+ position: absolute;
+}
+
+.tl {
+ right: 120px;
+ bottom: 120px;
+}
+
+.tr {
+ left: 120px;
+ bottom: 120px;
+}
+
+.bl {
+ right: 120px;
+ top: 120px;
+}
+
+.br {
+ left: 120px;
+ top: 120px;
+}
+</style>
+<div class=abs-cb>
+ <div id=s class=scroller>
+ <div class=filler></div>
+ <div class=anchor></div>
+ <div class=filler></div>
+ <div class="positioned tl dn"></div>
+ <div class="positioned tr dn"></div>
+ <div class="positioned bl dn"></div>
+ <div class="positioned br dn"></div>
+ </div>
+</div>
+<script>
+s.scrollTop = 120;
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/css-anchor-position/position-area-anchor-002.html b/testing/web-platform/tests/css/css-anchor-position/position-area-anchor-002.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>anchor() resolution in position-area</title>
+<link rel="help" href="https://www.w3.org/TR/css-anchor-position/#position-area">
+<link rel="match" href="position-area-anchor-002-ref.html">
+<link rel="author" name="David Shin" href="mailto:dshin@mozilla.com">
+<style>
+.abs-cb {
+ width: 180px;
+ height: 180px;
+ position: relative;
+ border: 5px solid;
+}
+
+.scroller {
+ width: 100%;
+ height: 100%;
+ overflow: scroll;
+}
+
+.anchor {
+ width: 60px;
+ height: 60px;
+ margin-left: 60px;
+ anchor-name: --a;
+ background: pink;
+}
+
+.filler {
+ width: 1px;
+ height: 180px;
+}
+
+.positioned {
+ width: 30px;
+ height: 30px;
+ background: purple;
+ position: absolute;
+ position-anchor: --a;
+}
+
+.tl {
+ position-area: top left;
+ right: anchor(left);
+ bottom: anchor(top);
+}
+
+.tr {
+ position-area: top right;
+ left: anchor(right);
+ bottom: anchor(top);
+}
+
+.bl {
+ position-area: bottom left;
+ right: anchor(left);
+ top: anchor(bottom);
+}
+
+.br {
+ position-area: bottom right;
+ left: anchor(right);
+ top: anchor(bottom);
+}
+
+.dn {
+ display: none;
+}
+
+</style>
+<div class=abs-cb>
+ <div id=s class=scroller>
+ <div class=filler></div>
+ <div class=anchor></div>
+ <div class=filler></div>
+ <div class="positioned tl dn"></div>
+ <div class="positioned tr dn"></div>
+ <div class="positioned bl dn"></div>
+ <div class="positioned br dn"></div>
+ </div>
+</div>
+<script>
+function raf() {
+ return new Promise(resolve => requestAnimationFrame(resolve));
+}
+
+async function runTest() {
+ s.scrollTop = 120;
+ await raf();
+ await raf();
+
+ for(const e of s.querySelectorAll('.positioned')) {
+ e.classList.remove('dn');
+ }
+ document.documentElement.classList.remove('reftest-wait');
+}
+runTest();
+</script>
+</html>