1. Introduction
This section is not normative.
This is currently a delta spec over Scroll Snap 1.
Scroll experiences don’t always start at the beginning. Interactions with carousels, swipe controls, and listviews often intend to begin from some element which might not be positioned at the beginning of the scroll container. JavaScript is required to make the scroll container initially scrolled to that element. By enabling CSS to specify that an element should be initially scrolled to, both users, page authors and browsers benefit.
In addition to setting an initial scroll target, developers need insights and events into Scroll Snap. Events like which element is snapped on which axis, when the snap event is changing, when snap completes and conveniences for snapping to children programmatically.
1.1. First Layout
This event should follow the Animation code path. When animation objects are created and fire events, this is when a box has it’s first layout.
2. Motivating Examples
.carousel{ overflow-inline : auto; } .carousel .origin{ scroll-start-target : auto; }
< div class = "carousel" > < img src = "img1.jpg" > < img src = "img2.jpg" > < img src = "img3.jpg" class = "origin" > < img src = "img4.jpg" > < img src = "img5.jpg" > </ div >
.scrollport{ overflow-block : auto; } main{ scroll-start-target : auto; }
< div class = "scrollport" > < nav > ...</ nav > < main > ...</ main > </ div >
3. Setting Where Scroll Starts
3.1. The scroll-start-target property
3.1.1. Initial scroll target
The initial scroll target of a scroll container scrollcontainer is an element or pseudo-element whose 'scroll-start-target’property is non-none and whose nearest scroll container is scrollcontainer. When multiple such elements or pseudo-elements exist, user-agents should select the one which comes first in tree order. When no such element or pseudo-element exists, scrollcontainer’s initial scroll target is null.
-
Let target be the initial scroll target for scrollcontainer.
-
Let position be the result of running the steps to determine the scroll-into-view position of target with behavior set to "auto", block set to "start", inline set to "nearest", and scrolling box set to scrollcontainer.
-
Set scrollcontainer’s initial scroll position to position.
3.1.2. scroll-start-target Property Definition
Name: | scroll-start-target |
---|---|
Value: | [ none | auto ] |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Computed value: | see individual properties |
Canonical order: | per grammar |
Animation type: | none |
- none
- The element is not an initial scroll target.
- auto
- The element is potentially an initial scroll target for its nearest scroll container ancestor.
3.1.3. Interaction with place-content
If a scroll container’s initial scroll position is potentially set by both a content-distribution property and by scroll-start-target on a descendant, scroll-start-target wins.
3.1.4. Post-first layout arrivals
While the document is being updated, a scroll container’s initial scroll target might arrive after that scroll container has been laid out. If this happens, user agents should still scroll to the initial scroll target unless the user agent has reason to believe the user is no longer interested in scrolling to the initial scroll position.
4. Styling Snapped Items
The ':snapped' pseudo-class is being dropped in favor of a container state query approach.
4.1. The Snapped-element Pseudo-class: :snapped
The :snapped pseudo-class matches any scroll snap targets, regardless of axis. The longform physical and logical pseudo-class selectors allow for more finite snapped children styling as they can target an individual axis.
More specific options are defined as follows:
- :snapped-x
- Matches the child snapped on the horizontal axis.
- :snapped-y
- Matches the child snapped on the vertical axis.
- :snapped-inline
- Matches the child snapped on the inline axis.
- :snapped-block
- Matches the child snapped on the block axis.
Note: Issue #6985
Need to figure out resolution of the initial frame.
5. Snap Events
5.1. scrollsnapchange
and scrollsnapchanging
CSS scroll snap points are often used as a mechanism to create scroll interactive "selection" components, where selection is determined with JavaScript intersection observers and a scroll end guestimate. By creating a built-in event, the invisible state will become actionable, at the right time, and always correct.
5.1.1. Snap Targets
A snap target is an element or pseudo-element which the user-agent has chosen to snap a given snap container to.
Event | Interface | Targets | Description |
---|---|---|---|
scrollsnapchange
| SnapEvent
| scroll containers | Fired at the scrolling element or Document at the end of a scroll (before a scrollend event)
or after a layout snap if the snap targets that the scrolling element or Document is snapped to changed.
|
scrollsnapchanging
| SnapEvent
| scroll containers | Fired at the scrolling element or Document during scrolling (before a scroll event),
if the snap targets that the scrolling would cause the scroller to snap to are
different from the snap targets selected at the last scrollsnapchanging event that was fired.
|
5.1.2. scrollsnapchange
scrollsnapchange
indicates that the snap area to which a snap container is snapped along either axis has changed. scrollsnapchange
is dispatched:
- when a scrolling operation is completed if, for either the block or inline axis, the snap target which the snap container is snapped to is different from the snap target it most recently snapped to in that axis. For snap containers with proximity strictness, the scroll may result in the snap container no longer being snapped to any snap target. CSS Scroll Snap 1 § 6.2 Choosing Snap Positions describes the method a UA follows when choosing between elements or pseudo-elements which are snap areas.
- if there is a change to a snap container’s style such that it goes from having a non-none value for scroll-snap-type to having a none value or vice versa.
- if, after a layout change, the snap target to which a snap container is snapped to changes, regardless of whether there is a change in scroll position after the layout change.
Scrolling operations always lead to scrollend
events being fired. If a
scrolling operation also results in a scrollsnapchange
event being fired, the scrollsnapchange
event should be fired before the scrollend
event.
Each Document
has an associated list of pending scrollsnapchange event targets, initially empty.
Each snap container has one scrollsnapchangeTargetBlock and one scrollsnapchangeTargetInline in the block and inline axes respectively, each of which can either be null if the container is not snapped in that axis or the snap target to which the container is snapped.
When asked to update scrollsnapchange targets for a snap container, snapcontainer, run these steps:
-
Let doc be snapcontainer’s associated
Document
. -
Let blockTarget be the scrollsnapchangeTargetBlock associated with snapcontainer.
-
Let inlineTarget be the scrollsnapchangeTargetInline associated with snapcontainer.
-
Let blockScrollSnapchangingTarget be the scrollsnapchanging block-axis target associated with snapcontainer.
-
Let inlineScrollSnapchangingTarget be the scrollsnapchanging inline-axis target associated with snapcontainer.
-
Let snap targets changed be a boolean flag that is initially false.
-
If blockTarget is not the same snap target as blockScrollSnapchangingTarget or
-
Set the scrollsnapchangeTargetBlock associated with snapcontainer to blockScrollSnapchangingTarget.
-
Set snap targets changed to true.
-
-
If inlineTarget is not the same snap target as inlineScrollSnapchangingTarget:
-
Set the scrollsnapchangeTargetInline associated with snapcontainer to inlineScrollSnapchangingTarget.
-
Set snap targets changed to true.
-
-
If snap targets changed is true:
-
If snapcontainer is not already in doc’s pending scrollsnapchange event targets:
-
Append snapcontainer to doc’s pending scrollsnapchange event targets.
-
-
Note: When snapping occurs on a scroller (either due to a layout change or a
scrolling operation) the scrollsnapchanging block-axis target and scrollsnapchanging inline-axis target associated with that scroller are updated and represent the current snap targets
of that scroller. This allows the update scrollsnapchange targets algorithm
to use these snap targets to determine whether a scrollsnapchange
event should be fired.
When asked to dispatch pending scrollsnapchange events for a Document
, doc, run these steps:
-
For each item target in doc’s pending scrollsnapchange event targets:
-
Let blockTarget and inlineTarget be null initially.
-
If the scrollsnapchangeTargetBlock associated with target is a pseudo-element, set blockTarget to the owning element of that scrollsnapchangeTargetBlock.
-
Otherwise, set blockTarget to that scrollsnapchangeTargetBlock.
-
If the scrollsnapchangeTargetInline associated with target is a pseudo-element, set inlineTarget to the owning element of that scrollsnapchangeTargetInline.
-
Otherwise, Set inlineTarget to that scrollsnapchangeTargetInline.
-
Fire a
SnapEvent
, snapevent, namedscrollsnapchange
at target and let snapevent’ssnapTargetBlock
andsnapTargetInline
attributes be blockTarget and inlineTarget respectively.
-
-
Empty doc’s pending scrollsnapchange event targets.
5.1.3. scrollsnapchanging
scrollsnapchanging
is dispatched:
-
during a scrolling operation, if the snap targets to which a snap container would snap (in either axis) changes, or
-
if a layout change occurs such that a
scrollsnapchange
event is to be dispatched. In this case, as with the scrolling case, thescrollsnapchanging
event should be dispatched before thescrollsnapchange
event.
A scrolling operation might animate towards a particular position (e.g. scrollbar arrow clicks, arrow key presses, "behavior: smooth" programmatic scrolls) or might directly track a user’s input (e.g. touch scrolling, scrollbar dragging). In either case, the user agent chooses an eventual snap target in each axis to which the scroller will snap after the scrolling operation reaches its intended scroll position.
-
In the former case, the intended scroll position is the scroll animation’s target scroll offset.
-
In the latter case, the intended scroll position is the current scroll offset as determined by the user’s input.
scrollsnapchanging
aims to let the web page know, as early as possible,
that the scrolling operation will result in a change in the snap target the snap
container is snapped to. The user agent should evaluate whether to trigger scrollsnapchanging
based on the eventual snap target to which the scroller would snap were the scrolling operation
to reach its intended scroll position.
Note: Since scrollsnapchanging gives the web page hints about future snapping, the snapping hinted at by a scrollsnapchanging event might not materialize since it will be possible for subsequent scrolling input to further alter the snap container’s scroll position and result in a different eventual snap target.
scrollsnapchanging
events are fired before scroll
events.
Each Document
has an associated list of pending scrollsnapchanging event targets, initially empty.
Each snap container has one scrollsnapchanging block-axis target and one scrollsnapchanging inline-axis target in the block and inline axes respectively, each of which can either be null if the container is not snapping in that axis or the snap target to which the container is snapping.
When asked to update scrollsnapchanging targets for a snap container, snapcontainer, given an snap target newBlockTarget and an snap target newInlineTarget, run these steps:
-
Let doc be snapcontainer’s associated
Document
. -
Let blockTarget be the scrollsnapchanging block-axis target that is associated with snapcontainer.
-
Let inlineTarget be the scrollsnapchanging inline-axis target that is associated with snapcontainer.
-
If newBlockTarget is not the same snap target as blockTarget:
-
Set the scrollsnapchanging block-axis target associated with snapcontainer to newBlockTarget.
-
If snapcontainer is not already in doc’s pending scrollsnapchanging event targets,
-
Append snapcontainer to doc’s pending scrollsnapchanging event targets
-
-
-
If newInlineTarget is not the same snap target as inlineTarget:
-
Set the scrollsnapchanging inline-axis target associated with snapcontainer to newInlineTarget.
-
If snapcontainer is not already in doc’s pending scrollsnapchanging event targets,
-
Append snapcontainer to doc’s pending scrollsnapchanging event targets.
-
-
When asked to dispatch pending scrollsnapchanging events for a Document
, doc, run these steps:
-
For each item target in doc’s pending scrollsnapchanging event targets:
-
Let blockTarget and inlineTarget be null initially.
-
If the scrollsnapchanging block-axis target associated with target is a pseudo-element, set blockTarget to the owning element of that scrollsnapchanging block-axis target.
-
Otherwise, set blockTarget to that scrollsnapchanging block-axis target.
-
If the scrollsnapchanging inline-axis target associated with target is a pseudo-element, set inlineTarget to the owning element of that scrollsnapchanging inline-axis target.
-
Otherwise, set inlineTarget to that scrollsnapchanging inline-axis target.
-
Fire a
SnapEvent
, snapevent, namedscrollsnapchanging
at target and let snapevent’ssnapTargetBlock
andsnapTargetInline
attributes be blockTarget and inlineTarget, respectively.
-
-
Empty doc’s pending scrollsnapchanging event targets.
5.1.4. Snap Events due to Layout Changes
When a snap container, snapcontainer, re-snaps, run these steps:-
Let newBlockTarget be the snap target that snapcontainer has snapped to in the block axis or null if it did not snap to any element.
-
Let newInlineTarget be the snap target that snapcontainer has snapped to in the inline axis or null if it did not snap to any element or pseudo-element.
-
Run the steps to update scrollsnapchanging targets with newBlockTarget as newBlockTarget and newInlineTarget as newInlineTarget.
-
Run the steps to update scrollsnapchange targets for snapcontainer.
5.2. SnapEvent interface
dictionary :
SnapEventInit EventInit {Node ?;
snapTargetBlock Node ?; }; [
snapTargetInline Exposed =Window ]interface :
SnapEvent Event {(
constructor DOMString ,
type optional SnapEventInit = {});
eventInitDict readonly attribute Node ?snapTargetBlock ;readonly attribute Node ?snapTargetInline ; };
snapTargetBlock
, of type Node, readonly, nullable-
The element that the snap container is snapped to in the block axis at the snap position for the associated snap event. If the snap target corresponding to this was a pseudo-element, this will be the owning element of that pseudo-element.
snapTargetInline
, of type Node, readonly, nullable-
The element that the snap container is snapped to in the inline axis at the snap position for the associated snap event. If the snap target corresponding to this was a pseudo-element, this will be the owning element of that pseudo-element.
For scrollsnapchange
events,
the snap position is the position
already realized by the snap container after a scroll snap.
For scrollsnapchanging
events
it is the snap position
that the snap container will eventually snap to
when the scrolling operation ends.
SnapEvent
s do not bubble except when the event target is the Document
. SnapEvent
s are not cancellable.
Appendix A: Event Handlers
This section should be moved to the HTML event handler specification.
Event handlers on elements, Document objects and Window objects
The following are additional event handlers (and their corresponding event handler event types)
that must be supported by all HTML elements as both event handler content attributes and event handler IDL attributes; and that must be supported by all Window
objects and Document
objects, as event handler IDL attributes:
Event handler | Event handler event type |
---|---|
onscrollsnapchange
| scrollsnapchange
|
onscrollsnapchanging
| scrollsnapchanging
|
Extensions to the GlobalEventHandlers
Interface Mixin
This specification extends the GlobalEventHandlers
interface mixin from
HTML to add event handler IDL attributes for SnapEvent
s as defined
in Event handlers on elements, Document objects and Window objects.
IDL Definition
partial interface mixin GlobalEventHandlers {attribute EventHandler ;
onsnapchanged attribute EventHandler ; };
onsnapchanging
6. Privacy Considerations
The features in this spec have no known privacy implications.
7. Security Considerations
The features in this spec have no known security implications.