commit 8b6a792b46dbda3ad8f78e54f020705a577095b1
parent 8a07a5b43aa737feb22c3174de57d15da7c670fd
Author: Johannes Odland <johannes.odland@nrk.no>
Date: Mon, 15 Dec 2025 18:06:46 +0000
Bug 2005934 – Reduce effective end edge of sticky view rectangle when smaller than border box of sticky box. r=emilio,layout-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D276366
Diffstat:
6 files changed, 50 insertions(+), 37 deletions(-)
diff --git a/layout/generic/StickyScrollContainer.cpp b/layout/generic/StickyScrollContainer.cpp
@@ -171,42 +171,61 @@ void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame,
nsMargin sfPadding = scrolledFrame->GetUsedPadding();
nsPoint sfOffset = aFrame->GetParent()->GetOffsetTo(scrolledFrame);
+ nsSize sfSize =
+ mScrollContainerFrame->GetScrolledFrameSizeAccountingForDynamicToolbar();
+ StyleDirection direction = cbFrame->StyleVisibility()->mDirection;
+ nsMargin effectiveOffsets = *computedOffsets;
+
+ if (computedOffsets->top != NS_AUTOOFFSET &&
+ computedOffsets->bottom != NS_AUTOOFFSET) {
+ // Decrease the effective end-edge inset of the sticky view rectangle
+ // when its height is less than the height of the border-box of the sticky
+ // box.
+ nscoord stickyViewHeight = sfSize.height - computedOffsets->TopBottom();
+ if (rect.height > stickyViewHeight) {
+ nscoord delta = rect.height - stickyViewHeight;
+ effectiveOffsets.bottom -= delta;
+ }
+ }
+
+ if (computedOffsets->left != NS_AUTOOFFSET &&
+ computedOffsets->right != NS_AUTOOFFSET) {
+ // Decrease the effective end-edge inset of the sticky view rectangle
+ // when its width is less than the width of the border-box of the sticky
+ // box.
+ nscoord stickyViewWidth = sfSize.width - computedOffsets->LeftRight();
+ if (rect.width > stickyViewWidth) {
+ nscoord delta = rect.width - stickyViewWidth;
+ if (direction == StyleDirection::Ltr) {
+ effectiveOffsets.right -= delta;
+ } else {
+ effectiveOffsets.left -= delta;
+ }
+ }
+ }
// Top
if (computedOffsets->top != NS_AUTOOFFSET) {
aStick->SetTopEdge(mScrollPosition.y + sfPadding.top +
- computedOffsets->top - sfOffset.y);
+ effectiveOffsets.top - sfOffset.y);
}
- nsSize sfSize =
- mScrollContainerFrame->GetScrolledFrameSizeAccountingForDynamicToolbar();
-
// Bottom
- if (computedOffsets->bottom != NS_AUTOOFFSET &&
- (computedOffsets->top == NS_AUTOOFFSET ||
- rect.height <= sfSize.height - computedOffsets->TopBottom())) {
+ if (computedOffsets->bottom != NS_AUTOOFFSET) {
aStick->SetBottomEdge(mScrollPosition.y + sfPadding.top + sfSize.height -
- computedOffsets->bottom - rect.height - sfOffset.y);
+ effectiveOffsets.bottom - rect.height - sfOffset.y);
}
- StyleDirection direction = cbFrame->StyleVisibility()->mDirection;
-
// Left
- if (computedOffsets->left != NS_AUTOOFFSET &&
- (computedOffsets->right == NS_AUTOOFFSET ||
- direction == StyleDirection::Ltr ||
- rect.width <= sfSize.width - computedOffsets->LeftRight())) {
+ if (computedOffsets->left != NS_AUTOOFFSET) {
aStick->SetLeftEdge(mScrollPosition.x + sfPadding.left +
- computedOffsets->left - sfOffset.x);
+ effectiveOffsets.left - sfOffset.x);
}
// Right
- if (computedOffsets->right != NS_AUTOOFFSET &&
- (computedOffsets->left == NS_AUTOOFFSET ||
- direction == StyleDirection::Rtl ||
- rect.width <= sfSize.width - computedOffsets->LeftRight())) {
+ if (computedOffsets->right != NS_AUTOOFFSET) {
aStick->SetRightEdge(mScrollPosition.x + sfPadding.left + sfSize.width -
- computedOffsets->right - rect.width - sfOffset.x);
+ effectiveOffsets.right - rect.width - sfOffset.x);
}
// These limits are for the bounding box of aFrame's continuations. Convert
diff --git a/layout/reftests/position-sticky/overconstrained-1-ref.html b/layout/reftests/position-sticky/overconstrained-1-ref.html
@@ -10,6 +10,8 @@
overflow: hidden;
}
#sticky {
+ position: relative;
+ top: 10px;
height: 81px;
background-color: black;
}
@@ -17,9 +19,7 @@
</head>
<body>
<div id="scroll">
- <div style="height: 95px"></div>
<div id="sticky"></div>
- <div style="height: 100px"></div>
</div>
</body>
</html>
diff --git a/layout/reftests/position-sticky/overconstrained-2-ref.html b/layout/reftests/position-sticky/overconstrained-2-ref.html
@@ -15,16 +15,9 @@
#scroll div {
display: inline-block;
}
- .fill {
- width: 99px;
- height: 1px;
- }
- #contain {
- width: 200px;
- height: 10px;
- background-color: gray;
- }
#sticky {
+ position: relative;
+ left: 10px;
width: 81px;
height: 10px;
background-color: black;
@@ -32,9 +25,7 @@
</style>
<body>
<div id="scroll">
- <div class="fill"></div
- ><div id="sticky"></div
- ><div class="fill"></div>
+ <div id="sticky"></div>
</div>
</body>
</html>
diff --git a/layout/reftests/position-sticky/overconstrained-2.html b/layout/reftests/position-sticky/overconstrained-2.html
@@ -6,7 +6,7 @@
<title>CSS Test: Sticky Positioning - left+right, overconstrained</title>
<link rel="author" title="Corey Ford" href="mailto:cford@mozilla.com">
<link rel="match" href="overconstrained-2-ref.html">
- <meta name="assert" content="Left+right-sticky with a wide element in an LTR container: should not act as right-sticky">
+ <meta name="assert" content="Left+right-sticky with a wide element in an LTR container: right inset should decrease">
<style>
#scroll {
width: 100px;
diff --git a/layout/reftests/position-sticky/overconstrained-3-ref.html b/layout/reftests/position-sticky/overconstrained-3-ref.html
@@ -10,12 +10,15 @@
height: 100px;
border: 1px solid black;
white-space: nowrap;
+ direction: rtl;
}
#scroll div {
display: inline-block;
}
#sticky {
- width: 1px;
+ position: relative;
+ right: 10px;
+ width: 81px;
height: 10px;
background-color: black;
}
diff --git a/layout/reftests/position-sticky/overconstrained-3.html b/layout/reftests/position-sticky/overconstrained-3.html
@@ -7,7 +7,7 @@
<link rel="author" title="Corey Ford" href="mailto:cford@mozilla.com">
<link rel="match" href="overconstrained-3-ref.html">
<meta name="flags" content="dom">
- <meta name="assert" content="Left+right-sticky with a wide element in an RTL container: should not act as left-sticky">
+ <meta name="assert" content="Left+right-sticky with a wide element in an RTL container: left inset should decrease">
<style>
#scroll {
width: 100px;