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

Reply via email to