Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 0beb8b67a954e4e9017b8d78b319bc4667a2b587
      
https://github.com/WebKit/WebKit/commit/0beb8b67a954e4e9017b8d78b319bc4667a2b587
  Author: Ahmad Saleem <[email protected]>
  Date:   2026-07-17 (Fri, 17 Jul 2026)

  Changed paths:
    A 
LayoutTests/fast/scrolling/resnap-focused-offscreen-overflow-scaled-expected.txt
    A LayoutTests/fast/scrolling/resnap-focused-offscreen-overflow-scaled.html
    M 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-expected.txt
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-scaled-ancestor-expected.txt
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-scaled-ancestor.html
    M Source/WebCore/platform/ScrollSnapAnimatorState.cpp
    M Source/WebCore/platform/ScrollSnapAnimatorState.h

  Log Message:
  -----------
  [CSS Scroll Snap] Re-snap should ignore a focused snap area that is scrolled 
out of the snapport
https://bugs.webkit.org/show_bug.cgi?id=319562
rdar://182390905

Reviewed by Simon Fraser.

When multiple snap areas are aligned at a scroll position, the re-snap
algorithm prefers a focused (or fragment-targeted) area over the others.
We applied that preference unconditionally, even when the focused area's
scroll snap area is scrolled entirely outside the snapport in the axis
that is not snapping. Per css-scroll-snap "Scoping Valid Snap Positions
to Visible Boxes" [1], such a scroll position is not a valid snap
position, so the focused area must not win the preference; the scroll
container should snap to an aligned area that is actually visible.

The scroll path already enforces this in closestSnapOffset() via
findCompatibleSnapArea(), but the re-snap/selection path did not, so a
focused-but-offscreen area could keep the scroller pinned to an invalid
offset after a layout change.

Evaluate the same cross-axis visibility in the selection path, at the
current scroll position (recorded on each snap/re-snap), rather than at
offset-collection time (which is tied to layout timing and would make
results depend on when snap offsets were last computed). Only areas in a
container that does not snap in the cross axis are affected; a container
that snaps in both axes can bring the area into view by snapping the
other axis, so it is left to closestSnapOffset()'s 2D handling.

The recorded scroll offset and viewport size are converted from client
coordinates by dividing out the page scale factor, matching the
convention used elsewhere in this file (closestSnapPointForOffset(),
adjustedScrollDestination(), targetOffsetForStartOffset()). Added two
tests: one WebKit-specific, pinch-zooming the main frame around an
overflow scroller (which always reports a page scale factor of 1) to
exercise that conversion directly; and one cross-browser WPT test using
a scaled ancestor (transform: scale()) as a portable stand-in for the
same coordinate-space concern, since page scale factor isn't scriptable
outside WebKit.

[1] https://drafts.csswg.org/css-scroll-snap/#snap-scope

* Source/WebCore/platform/ScrollSnapAnimatorState.cpp:
(WebCore::ScrollSnapAnimatorState::selectSnapTargetForAxis): Ignore the
focus/target preference when the representative area is off-screen in a
non-snapping cross axis, and drop off-screen areas from the candidate list.
(WebCore::ScrollSnapAnimatorState::innermostAlignedAreaIndicesForAxis):
Skip areas that are off-screen in a non-snapping cross axis.
(WebCore::ScrollSnapAnimatorState::isSnapAreaVisibleInCrossAxis): Added.
(WebCore::ScrollSnapAnimatorState::focusedOrTargetedBox): Made a member and
made it skip areas off-screen in a non-snapping cross axis.
(WebCore::ScrollSnapAnimatorState::resnapAfterLayout): Record the scroll
offset and viewport size used by the visibility check.
(WebCore::ScrollSnapAnimatorState::setNearestScrollSnapIndexForOffset): Ditto.
(WebCore::focusedOrTargetedBox): Deleted.
* Source/WebCore/platform/ScrollSnapAnimatorState.h:
* 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-expected.txt:
Progression.
* 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-scaled-ancestor.html:
 Added.
* 
LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-snap/snap-after-relayout/multiple-aligned-targets/prefer-focused-element-scaled-ancestor-expected.txt:
 Added.
* LayoutTests/fast/scrolling/resnap-focused-offscreen-overflow-scaled.html: 
Added.
* 
LayoutTests/fast/scrolling/resnap-focused-offscreen-overflow-scaled-expected.txt:
 Added.

Canonical link: https://commits.webkit.org/317447@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to