@@ -262,7 +262,7 @@ Snap Events {#snap-events}
262262████████ ███ ████████ ██ ██ ██ ██████
263263-->
264264
265- {{snapChanged }} and {{snapChanging }} {#snapchanged-and-snapchanging}
265+ {{snapchanged }} and {{snapchanging }} {#snapchanged-and-snapchanging}
266266--------------------------------------------
267267
268268 CSS scroll snap points are often used as a mechanism to
@@ -275,119 +275,250 @@ Snap Events {#snap-events}
275275 <table class="data" id="eventhandlers">
276276 <thead>
277277 <tr>
278- <th> Event handler
279- <th> Event handler event type
278+ <th> Event</th>
279+ <th> Interface</th>
280+ <th> Targets</th>
281+ <th> Description</th>
282+ </tr>
283+ </thead>
280284 <tbody>
281285 <tr>
282- <th> <dfn event>snapChanged</dfn>
283- <td> {{scroll!!event}}
286+ <th> <dfn for="snapchanged" event>snapchanged</dfn> </th>
287+ <td> {{SnapEvent}} </td>
288+ <td> scroll containers</td>
289+ <td> Fired at the scrolling element or {{Document}} at the end of a scroll (before a {{scrollend}} event)
290+ or after a <a href="https://drafts.csswg.org/css-scroll-snap-1/#re-snap">layout snap</a>
291+ if the element that the scrolling element or Document is snapped to changed.</td>
292+ </tr>
284293 <tr>
285- <th> <dfn event>snapChanging</dfn>
286- <td> {{scroll!!event}}
294+ <th> <dfn for="snapchanging" event>snapchanging</dfn> </th>
295+ <td> {{SnapEvent}} </td>
296+ <td> scroll containers</td>
297+ <td> Fired at the scrolling element or {{Document}} during scrolling (before a {{scroll}} event),
298+ if the element that the scrolling would cause the scroller to snap to is
299+ different from the target reported by the last snapchanging event that was fired.</td>
300+ </tr>
301+ </tbody>
287302 </table>
288- <h4>SnapEvents</h4>
289- <pre class="idl">
290- [Exposed=Window]
291- interface SnapEvent : Event {
292- constructor(DOMString type, optional SnapEventInit eventInitDict = {});
293- readonly attribute EventTarget? target;
294- readonly attribute SnapTargetList snappedTargets;
295- readonly attribute SnapTargetList snapTargets;
296- readonly attribute boolean invokedProgrammatically;
297- readonly attribute boolean smoothlyScrolled;
298- };
299303
300- [Exposed=Window]
301- interface SnapTargetList {
302- readonly attribute SnapTargetArray x;
303- readonly attribute SnapTargetArray y;
304+ <h4 for="snapchanged" id="snapchanged"> snapchanged </h4>
305+ {{snapchanged}} indicates that the snap area to which a snap container is snapped along either axis has changed.
306+ {{snapchanged}} is dispatched:
307+
308+ <ol>
309+ <li>
310+ when a scrolling operation is <a spec="cssom-view-1" lt="scroll completed">completed</a>
311+ if, for either the block or inline axis, the
312+ element which the snap container is snapped to is different from the element
313+ it most recently snapped to in that axis. For snap containers with
314+ ''scroll-snap-type/proximity'' strictness, the scroll may result in the snap
315+ container no longer being snapped to any element. [[css-scroll-snap-1#choosing]]
316+ describes the method a UA follows when choosing between elements which are
317+ <a spec="css-scroll-snap-1" lt="scroll snap area">snap areas</a> .
318+ </li>
319+ <li> if there is a change to a snap container's style such that it goes from
320+ having a non-'none' value for [[css-scroll-snap-1#scroll-snap-type|scroll-snap-type]]
321+ to having a 'none' value or vice versa.
322+ </li>
323+ <li> if, after a [[css-scroll-snap-1#re-snap|layout change]] , the element to
324+ which a snap container is snapped to changes, regardless of whether there is
325+ a change in scroll position after the layout change.
326+ </li>
327+ </ol>
328+
329+ Scrolling operations always lead to {{scrollend}} events being fired. If a
330+ scrolling operation also results in a {{snapchanged}} event being fired, the
331+ {{snapchanged}} event should be fired before the {{scrollend}} event.
332+
333+ Each {{Document}} has an associated list of
334+ <dfn export for=Document>pending snapchanged event targets</dfn> , initially empty.
335+
336+ Each
337+ <a spec=css-scroll-snap lt="scroll snap container">snap container</a> has
338+ one <dfn export>snapchangedTargetBlock</dfn> and one
339+ <dfn export>snapchangedTargetInline</dfn> in the block and inline axes
340+ respectively, each of which can either be null if the container is not
341+ snapped in that axis or the {{Element}} to which the container is snapped.
342+
343+ When asked to <dfn export for=Document>update snapchanged targets</dfn>
344+ for a <a spec=css-scroll-snap lt="scroll snap container">snap container</a> ,
345+ |snapcontainer|, run these steps:
346+
347+ 1. Let <var> doc</var> be |snapcontainer|'s associated {{Document}} .
348+ 1. Let <var> blockTarget</var> be the <a>snapchangedTargetBlock</a> associated
349+ with |snapcontainer|.
350+ 1. Let <var> inlineTarget</var> be the <a>snapchangedTargetInline</a> associated
351+ with |snapcontainer|.
352+ 1. Let <var> blockSnapchangingTarget</var> be the <a>snapchangingTargetBlock</a>
353+ associated with |snapcontainer|.
354+ 1. Let <var> inlineSnapchangingTarget</var> be the
355+ <a>snapchangingTargetInline</a> associated with |snapcontainer|.
356+ 1. Let <var> snap targets changed</var> be a boolean flag that is initially false.
357+ 1. If <var> blockTarget</var> is not the same element as <var> blockSnapchangingTarget</var> or
358+ 1. Set the <a>snapchangedTargetBlock</a> associated with |snapcontainer| to
359+ <var> blockSnapchangingTarget</var> .
360+ 1. Set <var> snap targets changed</var> to true.
361+ 1. If <var> inlineTarget</var> is not the same element as <var> inlineSnapchangingTarget</var> :
362+ 1. Set the <a>snapchangedTargetInline</a> associated with |snapcontainer| to
363+ <var> inlineSnapchangingTarget</var> .
364+ 1. Set <var> snap targets changed</var> to true.
365+ 1. If <var> snap targets changed</var> is true:
366+ 1. If |snapcontainer| is not already in <var> doc</var> 's
367+ <a>pending snapchanged event targets</a> :
368+ 1. Append |snapcontainer| to <var> doc</var> 's
369+ <a>pending snapchanged event targets</a> .
370+
371+ Note: When snapping occurs on a scroller (either due to a layout change or a
372+ scrolling operation) the <a>snapchangingTargetBlock</a> and <a>snapchangingTargetInline</a>
373+ associated with that scroller are updated and represent the current snap targets
374+ of that scroller. This allows the <a>update snapchanged targets</a> algorithm
375+ to use these elements to determine whether a {{snapchanged}} event should be fired.
376+
377+ When asked to <dfn>dispatch pending snapchanged events</dfn> for a {{Document}} ,
378+ <var> doc</var> , run these steps:
379+ 1. For each item <var> target</var> in |doc|'s <a>pending snapchanged event targets</a> :
380+ 1. Fire a {{SnapEvent}} , |snapevent|, named {{snapchanged}} at <var> target</var>
381+ and let |snapevent|'s {{SnapEvent/snapTargetBlock}} and
382+ {{SnapEvent/snapTargetInline}} attributes be the <a>snapchangedTargetBlock</a> and the
383+ <a>snapchangedTargetInline</a> , respectively, that are associated with <var> target</var> .
384+ 1. Empty <var> doc</var> 's <a>pending snapchanged event targets</a> .
385+
386+ <h4 id="snapchanging"> snapchanging </h4>
387+ {{snapchanging}} is dispatched:
388+ * during a scrolling operation, if the element to which a
389+ <a spec=css-scroll-snap lt="scroll snap container">snap container</a> would
390+ <a spec="css-scroll-snap-1" lt="scroll snap">snap</a> (in either axis) changes, or
391+ * if a [[css-scroll-snap-1#re-snap|layout change]] occurs such that a {{snapchanged}} event
392+ is to be dispatched. In this case, as with the scrolling case, the {{snapchanging}} event
393+ should be dispatched before the {{snapchanged}} event.
394+
395+ A scrolling operation might animate towards a particular position (e.g.
396+ scrollbar arrow clicks, arrow key presses, "behavior: smooth" programmatic
397+ scrolls) or might directly track a user's input (e.g. touch scrolling, scrollbar
398+ dragging). In either case, the user agent [[css-scroll-snap-1#choosing|chooses]] an
399+ <dfn>eventual snap target</dfn> in each axis to which the scroller will
400+ <a spec="css-scroll-snap-1" lt="scroll snap">snap</a> after the scrolling operation
401+ reaches its intended scroll position.
402+ * In the former case, the intended scroll position is the scroll animation's
403+ target scroll offset.
404+ * In the latter case, the intended scroll position is the current scroll offset as
405+ determined by the user's input.
406+
407+ {{snapchanging}} aims to let the web page know, as early as possible,
408+ that the scrolling operation will result in a change in the element the snap
409+ container is snapped to. The user agent should evaluate whether to trigger
410+ {{snapchanging}} based on the <a>eventual snap target</a> to which the scroller would
411+ <a spec="css-scroll-snap-1" lt="scroll snap">snap</a> were the scrolling operation
412+ to reach its intended scroll position.
413+
414+ Note: Since snapchanging gives the web page hints about future snapping,
415+ the snapping hinted at by a snapchanging event might not materialize since it
416+ will be possible for subsequent scrolling input to further alter the snap
417+ container's scroll position and result in a different eventual snap target.
418+
419+
420+ {{snapchanging}} events are fired before {{scroll}} events.
421+
422+ Each {{Document}} has an associated list of
423+ <dfn export for=Document>pending snapchanging event targets</dfn> , initially empty.
424+
425+ Each
426+ <a spec=css-scroll-snap lt="scroll snap container">snap container</a> has
427+ one <dfn>snapchangingTargetBlock</dfn>
428+ and one <dfn>snapchangingTargetInline</dfn> in the block and inline axes
429+ respectively, each of which can either be null if the container is not
430+ snapping in that axis or the {{Element}} to which the container is snapping.
431+
432+ When asked to <dfn export for=Document>update snapchanging targets</dfn>
433+ for a <a spec=css-scroll-snap lt="scroll snap container">snap container</a> ,
434+ |snapcontainer|, given an {{Element}} newBlockTarget and an {{Element}}
435+ newInlineTarget, run these steps:
436+
437+ 1. Let <var> doc</var> be |snapcontainer|'s associated {{Document}} .
438+ 1. Let <var> blockTarget</var> be the <a>snapchangingTargetBlock</a> that is
439+ associated with |snapcontainer|.
440+ 1. Let <var> inlineTarget</var> be the <a>snapchangingTargetInline</a> that is
441+ associated with |snapcontainer|.
442+ 1. If <var> newBlockTarget</var> is not the same element as <var> blockTarget</var> :
443+ 1. Set the <a>snapchangingTargetBlock</a> associated with |snapcontainer| to
444+ <var> newBlockTarget</var> .
445+ 1. If |snapcontainer| is not already in <var> doc</var> 's
446+ <a>pending snapchanging event targets</a> ,
447+ 1. Append |snapcontainer| to <var> doc</var> 's
448+ <a>pending snapchanging event targets</a>
449+ 1. If <var> newInlineTarget</var> is not the same element as <var> inlineTarget</var> :
450+ 1. Set the <a>snapchangingTargetInline</a> associated with |snapcontainer| to
451+ <var> newInlineTarget</var> .
452+ 1. If |snapcontainer| is not already in <var> doc</var> 's
453+ <a>pending snapchanging event targets</a> ,
454+ 1. Append |snapcontainer| to <var> doc</var> 's
455+ <a>pending snapchanging event targets</a> .
456+
457+ When asked to <dfn>dispatch pending snapchanging events</dfn> for a {{Document}} ,
458+ <var> doc</var> , run these steps:
459+ 1. For each item <var> target</var> in |doc|'s <a>pending snapchanging event targets</a> :
460+ 1. Fire a {{SnapEvent}} , |snapevent|, named {{snapchanging}} at <var> target</var>
461+ and let |snapevent|'s {{SnapEvent/snapTargetBlock}} and
462+ {{SnapEvent/snapTargetInline}} attributes be the <a>snapchangingTargetBlock</a> and the
463+ <a>snapchangingTargetInline</a> , respectively, that are associated with <var> target</var> .
464+ 1. Empty <var> doc</var> 's <a>pending snapchanging event targets</a> .
465+
466+ <h4 id="snap-events-on-layout-changes">Snap Events due to Layout Changes </h4>
467+ When a <a spec=css-scroll-snap lt="scroll snap container">snap container</a> ,
468+ |snapcontainer|, [[css-scroll-snap-1#re-snap|re-snaps]] , run these steps:
469+
470+ 1. Let <var> newBlockTarget</var> be the element that |snapcontainer| has
471+ <a spec="css-scroll-snap-1" lt="scroll snap">snapped</a> to
472+ in the block axis or null if it did not snap to any element.
473+ 1. Let <var> newInlineTarget</var> be the element that |snapcontainer| has
474+ <a spec="css-scroll-snap-1" lt="scroll snap">snapped</a> to
475+ in the inline axis or null if it did not snap to any element.
476+ 1. Run the steps to <a>update snapchanging targets</a> with <var> newBlockTarget</var>
477+ as newBlockTarget and <var> newInlineTarget</var> as newInlineTarget.
478+ 1. Run the steps to <a>update snapchanged targets</a> for |snapcontainer|.
479+
480+
481+ SnapEvent interface
482+ -------------------
483+
484+ <pre class="idl">
485+ dictionary SnapEventInit : EventInit {
486+ Node? snapTargetBlock;
487+ Node? snapTargetInline;
304488 };
305489
306490 [Exposed=Window]
307- interface SnapTargetArray {
308- readonly attribute unsigned long length;
309- getter EventTarget? item (unsigned long index);
491+ interface SnapEvent : Event {
492+ constructor(DOMString type, optional SnapEventInit eventInitDict = {});
493+ readonly attribute Node? snapTargetBlock;
494+ readonly attribute Node? snapTargetInline;
310495 };
496+ </pre>
311497
312- dictionary SnapEventInit : EventModifierInit {
313- sequence<EventTarget> snappedTargetsX = [];
314- sequence<EventTarget> snappedTargetsY = [];
315- sequence<EventTarget> snapTargetsListX = [];
316- sequence<EventTarget> snapTargetsListY = [];
317- };
318- </pre>
498+ <dl>
499+ <div dfn-type=attribute class=attributes dfn-for="SnapEvent">
500+ : <dfn>snapTargetBlock</dfn>
501+ ::
502+ The element that the snap container is snapped to in the block axis
503+ at the <a spec="css-scroll-snap-1" lt="scroll snap position">snap position</a>
504+ for the associated snap event.
505+ </div>
506+ <div dfn-type=attribute class=attributes dfn-for="SnapEvent">
507+ : <dfn>snapTargetInline</dfn>
508+ ::
509+ The element that the snap container is snapped to in the inline axis
510+ at the <a spec="css-scroll-snap-1" lt="scroll snap position">snap position</a>
511+ for the associated snap event.
512+ </div>
513+
514+ For {{snapchanged}} events, the snap position is the position already
515+ realized by the snap container after a scroll snap. For {{snapchanging}}
516+ events it is the snap position that the snap container will eventually
517+ snap to when the scrolling operation ends.
319518
320- <dl>
321- <dt><code> SnapEvent . target</code></dt>
322- <dd>
323- This is the scroll container of the snapped-to element.
324- </dd>
325- <dt><code> SnapEvent . snappedTargets</code></dt>
326- <dd>
327- An object with 2 keys for each axis, each key returns an array of snapped targets.
328- </dd>
329- <dt><code> SnapEvent . snapTargets</code></dt>
330- <dd>
331- An object with 2 keys for each axis, each key returns an array of the aggregated snap children.
332- </dd>
333- <dt><code> SnapEvent . invokedProgrammatically</code></dt>
334- <dd>
335- A boolean informing developers if a user or script invoked scroll that caused <a>snapChanged</a> .
336- </dd>
337- <dt><code> SnapEvent . smoothlyScrolled</code></dt>
338- <dd>
339- A boolean informing developers if the snap change was instant or interpolated.
340- </dd>
341519 </dl>
342520
343- <h4> snapChanged </h4>
344-
345- The event is dispatched when a new snap target has been snapped to, providing what caused it.
346- It should be dispatched:
347-
348- * if user scroll interaction has ended and a new item has been rested on. If a user is still touching the screen or the touchpad, this event should not fire, even if the scroll position is exactly at a snapped element's position.
349- * if animations or transitions change the snapped style of the container or children, IF they have in fact changed the snap target.
350-
351- <table>
352- <tr><th> Type</th><td><strong><code> snapChanged</code></strong></td></tr>
353- <tr><th> Interface</th><td> {{SnapEvent}} </td></tr>
354- <tr><th> Sync / Async</th><td> Async</td></tr>
355- <tr><th> Bubbles</th><td> Yes</td></tr>
356- <tr><th> Trusted Targets</th><td><code> Element</code></td></tr>
357- <tr><th> Cancelable</th><td> No</td></tr>
358- <tr><th> Composed</th><td> Yes</td></tr>
359- <tr><th> Default action</th><td> None</td></tr>
360- <tr><th> Context<br/> (trusted events)</th><td><ul>
361- <li> {{Event}} .{{Event/target}} : scroll container of the snapped-to element</li>
362- <li> {{SnapEvent}} .{{snappedTargets}} : an object with 2 keys for each axis, each key returns an array of snapped targets</li>
363- <li> {{SnapEvent}} .{{snapTargets}} : an object with 2 keys for each axis, each key returns an array of the aggregated snap children</li>
364- <li> {{SnapEvent}} .{{invokedProgrammatically}} : a boolean informing developers if a user or script invoked scroll that caused <a>snapChanged</a> </li>
365- <li> {{SnapEvent}} .{{smoothlyScrolled}} : a boolean informing developers if the snap change was instant or interpolated</li>
366- </ul></td></tr>
367- </table>
368-
369- <h4> snapChanging </h4>
370-
371- Should fire every time, and as soon as, the UA has determined a new snap child until the new child is snapped to.
372-
373- <table>
374- <tr><th> Type</th><td><strong><code> snapChanging</code></strong></td></tr>
375- <tr><th> Interface</th><td> {{SnapEvent}} </td></tr>
376- <tr><th> Sync / Async</th><td> Async</td></tr>
377- <tr><th> Bubbles</th><td> Yes</td></tr>
378- <tr><th> Trusted Targets</th><td><code> Element</code></td></tr>
379- <tr><th> Cancelable</th><td> No</td></tr>
380- <tr><th> Composed</th><td> Yes</td></tr>
381- <tr><th> Default action</th><td> None</td></tr>
382- <tr><th> Context<br/> (trusted events)</th><td><ul>
383- <li> {{Event}} .{{Event/target}} : scroll container of the snapped-to element.</li>
384- <li> {{SnapEvent}} .{{snappedTargets}}
385- <li> {{SnapEvent}} .{{snapTargets}} : an object with 2 keys for each axis, each key returns an array of the aggregated snap children.</li>
386- <li> {{SnapEvent}} .{{invokedProgrammatically}} : a boolean informing developers if a user or script invoked scroll that caused <a>snapChanged.</a> </li>
387- <li> {{SnapEvent}} .{{smoothlyScrolled}} : a boolean informing developers if the snap change was instant or interpolated.</li>
388- </ul></td></tr>
389- </table>
390-
521+ A {{SnapEvent}} should not bubble and should not be cancellable.
391522<!--
392523██ ███████ ██ ██ ██████ ██ ██ ███ ██ ██ ████████ ██████
393524██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██
0 commit comments