Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 6977b801a5f6f803deb27f3e179a42964dd5647c
https://github.com/WebKit/WebKit/commit/6977b801a5f6f803deb27f3e179a42964dd5647c
Author: Wenson Hsieh <[email protected]>
Date: 2025-05-19 (Mon, 19 May 2025)
Changed paths:
A
LayoutTests/compositing/ios/clip-nested-fixed-in-sticky-container-expected.html
A LayoutTests/compositing/ios/clip-nested-fixed-in-sticky-container.html
M Source/WebCore/page/scrolling/ScrollingConstraints.cpp
M Source/WebCore/page/scrolling/ScrollingConstraints.h
M Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp
M Source/WebCore/page/scrolling/ScrollingTreeStickyNode.cpp
Log Message:
-----------
REGRESSION (294368@main): Fixed elements in sticky containers are incorrectly
positioned when scrolling
https://bugs.webkit.org/show_bug.cgi?id=293258
rdar://151649175
Reviewed by Abrar Rahman Protyasha.
When viewport clipping is enabled, nesting viewport-constrained children inside
sticky ancestors
may cause the viewport-constrained children to visually "lag behind" while
scrolling. While the
logic to compute post-layout clipping and anchor layer positions for the child
is correct, the
corresponding logic to reposition viewport-relative layers when scrolling (in
scrolling state and
tree nodes) is broken, which causes the anchor layer of the fixed/sticky child
to get stuck in the
same absolute position instead of moving along with the viewport rect.
This happens because we overcompensate for the sticky ancestor's
`scrollDeltaSinceLastCommit`, which
(before the viewport clipping changes) just returned how far the anchor layer
has moved since the
last layout. In the case where the sticky ancestor isn't constrained to the
viewport yet (and
therefore scrolls normally with the rest of the document), the anchor layer
hasn't moved at all, and
so the `scrollDeltaSinceLastCommit` should be empty.
With viewport clipping enabled, this now computes how far the clipping layer
has moved since the
last layout, which — in this case of a sticky-but-non-viewport-constrained
container — will be non-
zero, since the viewport clipping layer always needs to track the viewport rect.
Since `Scrolling{State|Tree}StickyNode::scrollDeltaSinceLastCommit` is only
used to adjust the
positions of child viewport-constrained elements nested inside of sticky
ancestors, the latter (new)
behavior is incorrect because these child elements are inserted under the
ancestor's anchor layer
(not the interstitial viewport clipping layer); in other words, when adjusting
the child element's
layer position to account for the sticky ancestor, we need to adjust for both
the anchor and
clipping layers (not just the clipping layer).
To fix this, we fix
`Scrolling{State|Tree}StickyNode::scrollDeltaSinceLastCommit` so that it returns
the delta between the current (computed) anchor layer position, and the anchor
layer position after
the last layout (both relative to the parent layer).
*
LayoutTests/compositing/ios/clip-nested-fixed-in-sticky-container-expected.html:
Added.
* LayoutTests/compositing/ios/clip-nested-fixed-in-sticky-container.html: Added.
Add a layout test to exercise the change by scrolling down in a webpage with a
fixed `nav` docked to
the top of the viewport, inside a sticky `main` element; verify that this
produces the same result
as if we didn't scroll at all.
* Source/WebCore/page/scrolling/ScrollingConstraints.cpp:
(WebCore::StickyPositionViewportConstraints::anchorLayerPositionForConstrainingRect
const):
(WebCore::StickyPositionViewportConstraints::anchorLayerPositionAtLastLayout
const):
Add a helper method to return the anchor layer position, relative to the sticky
element's parent. In
the case where the viewport clipping layer is present,
`m_layerPositionAtLastLayout` represents the
clipping layer's position, and `m_anchorLayerOffsetAtLastLayout` is the offset
of the anchor layer
within the clipping layer. In the case where viewport clipping is disabled for
this layer,
`m_layerPositionAtLastLayout` already represents the anchor layer position, and
`m_anchorLayerOffsetAtLastLayout` is always empty, since it represents the
offset of the anchor
layer relative to itself.
* Source/WebCore/page/scrolling/ScrollingConstraints.h:
* Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp:
(WebCore::ScrollingStateStickyNode::scrollDeltaSinceLastCommit const):
See description above for more details.
* Source/WebCore/page/scrolling/ScrollingTreeStickyNode.cpp:
(WebCore::ScrollingTreeStickyNode::scrollDeltaSinceLastCommit const):
Canonical link: https://commits.webkit.org/295143@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes