# CSS Scroll Snap Diff Annotations

This is a list of differences between the CSS Scroll Snap Module as maintained by Matt Rakow and the CSS Scroll Snap Module Change Proposal maintained by Tab and fantasai.

> At the most recent F2F the group agreed to accept a bunch of changes from Fantasai and Tab. Microsoft asked for some time to do a final review.

> While we don't have immediate plans to implement, it would be nice to get the specification stable soon. Can we set a deadline for review, after which we go ahead with the resolution from the meeting?

> I'm not sure how much time is necessary. Microsoft?

## Suggested Process

In the interests of F2F time, we are requesting that the WG adopt the following rapid-decision format for resolution of these changes:

1. First, a quick presentation of the change.
2. Second, a few minutes for people to peruse the change (if necessary), and to enter a straw poll in IRC:

   +1 | I agree with adopting the new wording.
   -1 | I disagree with adopting the new wording.
   +2 | I think the new wording is better than the old one, but I would like to see further improvements, which I will file as a follow-up issue.
   0 | I need more time to decide, please revisit this after the break (during which I promise to review the change, obviously).
   T | I need more time to decide, please revisit this tomorrow morning (at which point I promise to have an opinion or a damned good reason outside of my control to ask for more time).

Abstentions shall be recorded by omission. The chairs will ask by a show of hands if anyone needs another minute or two to decide, and otherwise swiftly end the poll.
3. If the straw poll results are reasonably conclusive, the chairs will record a resolution to adopt the change. If they are not conclusive, the chairs will open discussion.

Our goal in presenting this list is to close, by the end of the F2F, on all outstanding technical and editorial issues, and by formally adopting the exact wording changes necessary to resolve these issues, remove the need for any further spec-editor discretion in updating the spec. This will allow somebody who actually has the time (i.e. not Matt Rakow) to make the edits so that the spec can be 100% up-to-date by next week rather than sometime in the next six months maybe.

(Of course, not all of these edits are perfect, but insofar as they are better we would like the CSSWG to formally adopt them. Further review, edits, and improvements can then be made once there is a fully up-to-date consensus spec on /TR.)

## Specific Changes

Title Change Merged
  Robert O'Callahan requested a change to the name of the spec, because (with his requested changes) it's not about snappoing points, but about snapping box edges. (Issue 43 filed December 2013)

  > CSS Scroll Snap Points Module Level 1

  > http://www.w3.org/TR/css-snappoints scroll-snap-1/

Terminology Change: Scroll Snap Area Merged
  Tab and I introduced the term “scroll snap area” to refer to the rectangle being aligned within the viewport. Matt's version uses “scroll snap margin” to refer to this area. However the term “scroll snap margin” is misleading because the margin area of a box is the area inside the margin edges and outside its border box whereas the area of concern here includes the entire area of the defined rectangle.

      s/scroll snap margin/scroll snap area/g;

Error: border-box vs. margin-box Partially Merged
  Matt's spec parenthetically mentions that the scroll snap area defaults to the margin box. However, the spec actually defines that it defaults to the border box. This change corrects this error.

  > Snap positions can be specified as a particular alignment (scroll-snap-align) of an element’s scroll snap area (`scroll-snap-margin`, defaulting to its margin box its border box, as modified by `scroll-snap-margin`) within …

  (In the most recent changes, “margin box” has been replaced with “border box”, but the resulting text is awkward.)
Move: Undefined Animations and Physics Merged
  There is a statement in the definition of `scroll-snap-type` that, since it applies generally to scroll-snapping, we felt belonged in Overview section that defines the overall scroll-snapping model rather than specifically in `scroll-snap-type`.

  > It The CSS Scroll Snap Module intentionally does not specify nor mandate any precise animations or physics used to enforce snap positions; this is left up to the user agent.

Specifying Scroll-snap Axes Partially Merged
  The WG resolved on 2 December 2015 to specify, on a property applied to the scroll container, which axis(es) would be honored in scroll snapping. he following changes implement this:

  > Name: | scroll-snap-type
  > Value | none | [ proximity | mandatory ] || [ x | y | block | inline | both ]

  > The scroll-snap-type property defines … and which axes are considered.

  > The strictness values (none, proximity, mandatory) specify how strictly snap positions are enforced on the scroll container (by forcing an adjustment to the scroll offset). Values are defined as follows:

  > …

  > The axis values specify what axis(es) are affected by snap positions, and whether snap positions are evaluated independently per axis, or together as a 2D point. Values are defined as follows:

  > x
  >   The scroll container axis-snaps to snap positions in its horizontal axis only.
  > y
  >   The scroll container axis-snaps to snap positions in its vertical axis only.
  > block
  >   The scroll container axis-snaps to snap positions in its block axis only.
  > inline
  >   The scroll container axis-snaps to snap positions in its inline axis only.
  > both
  >   The scroll container axis-snaps to snap positions in both of its axises independently (potentially snapping to different elements in each axis).

  > If no axis value is specified, then the axis is automatically computed:

  > - If the scroll container is only scrollable in one axis (only one axis has its overflow set to auto or scroll) it axis-snaps in the scrollable axis only.

  > - Otherwise, it axis-snaps in its block axis only.

  There remains an open issue on whether there should be longhands for this and if so, what the shorthand/longhand names should be.

Trapping Merged
  In Sapporo, the WG resolved (27 October 2015) to have non-`none` values of the `scroll-snap-type` property “trap” descendant scroll snap positions in order to provide authors a way of blocking upward propagation of snap positions within a box’s content. (Issue 82 resolved TPAC 2015)

  In order to fix this, Tab and I adjusted the definitions of the `scroll-snap-type` strictness values as follows:

  > none

  >   If specified on a scroll container, …

  >   If specified on a non-scroll container, this value has no effect.

  > proximity

  >   If specified on a scroll container, …

  >   If specified on a non-scroll container, this value “traps” descendant boxes’ snap positions, preventing them from affecting any ancestor scroll containers.

  >   …

  > mandatory
  >   If specified on a scroll container, …

  >   If specified on a non-scroll container, this value “traps” descendant boxes’ snap positions, preventing them from affecting any ancestor scroll containers.

  >   …

  We also introduced the term “scroll snap container” (“snap container” for short) to represent the scroll container associated to a particular snap position. This term allows us to give a straightforward definition, in one single place, that accounts for the fact that the relevant box is found along the containing block chain, and also that it is intercepted by any intervening elements with a none-`none` value for `scroll-snap-type`.

  > The `scroll-snap-type` property specifies whether a scroll container is a scroll snap container …

  > A box captures snap positions if it is a scroll container or has a value other than `none` for `scroll-snap-type`. If a box’s nearest snap-position capturing ancestor on its containing block chain is a scroll container with a non-`none` value for `scroll-snap-type`, then that is the box’s scroll snap container. Otherwise, the box has no scroll snap container, and its specified snap positions do not trigger snapping.

  This also allows the following fix for some imprecise wording in the definition of `scroll-snap-align`:

  > The `scroll-snap-align` property specifies how an element’s scroll snap margin should align with its ancestor scroll container’s snap alignment container the box’s snap position as an alignment of its snap area (as the alignment subject) within its snap container’s snapport (as the alignment container).

RFC2119 Terminology Merged
  As much as I like the word “guarantee” in the description of `mandatory`, it seems more appropriate to use RFC2119’s “requirement”.

  > … the scroll container is guaranteed required …

Author Warning wrt Mandatory Snapping Merged
  Based on CSSWG discussions, we added a warning to authors about how despite our best efforts, they can still totally screw up the accessibility of the document, and should therefore avoid doing that.

  > Authors should use mandatory snap positions with consideration of varyingly-sized screens and (if applicable) varying-sized content. In particular, although access to snapped elements larger than the viewport is handled by the UA, if authors assign mandatory snapping to non-adjacent siblings, content in between can become inaccessible in cases where it is longer than the screen. 7

Resnapping Requirements
  - The first change here is to move the resnapping requirements to the end of the section. This is so that this deep technical detail does not get in the way of understanding what, overall, the `scroll-snap-type` values do. (This editorial movement is particularly important for authors reading the spec.) This also allows us to merge the two paragraphs, which are nearly identical, making the spec overall easier to read and less likely to contain inconsistencies.
  - As Resolved 20 January 2016, if the content changes, and we were either not previously snapped to a snap position or that snap position no longer exists, the UA must behave as if the user explicitly scrolled to that position, i.e. snapping if required. The following edits implement this requirement:

    > If the content changes (e.g. content is added, moved, deleted, resized), the UA must re-evaluate, and potentially re-snap if necessary, the resulting scroll offset once the positions of the content have restabilized. … (stuff about resnapping to the same position) … Otherwise, the scroll container must be re-snapped as if the user had scrolled to its current scroll offset (as an explicit scroll, if no other scroll operation is active).

  - Given those changes, and the fact that reachableness of snap positions is handled more generally elsewhere, the following edits clean up the ensuing prose so that the paragraph reads cleanly:

    > … If the content changes … such that the scroll container would no longer be snapped to the same snap position it was snapped to before the content change and that same snap position still exists (e.g. its associated element was not deleted) and is reachable, the scroll container must be re-snapped to that same snap position after the content change

    > … If the content changes … changes such that the scroll container would no longer be snapped (e.g. content is added, moved, deleted, resized) to the same snap position it was snapped to before the content change, the scroll container must be re-snapped. If the same snap position it was snapped to before the content change still exists (e.g. its associated element was not deleted) and is reachable, the scroll container must be re-snapped to that same snap position after the content change.

    > … If the content changes (e.g. content is added, moved, deleted, resized), the UA must re-evaluate, and potentially re-snap if necessary, the resulting scroll offset once the positions of the content have restabilized. However, if there was a previously-snapped snap position (associated with the same element) that still exists after such changes, the UA must remain snapped to it.

  - And this last set of insertions add some clarifications.

    > If the content or layout of the scroll container changes e.g. content is added, moved, deleted, resized), the UA must re-evaluate, and potentially re-snap if necessary, the resulting scroll offset once the positions of the content have restabilized. This can result in no snapping, (e.g. if there are no nearby snap positions for a proximity-snapping scroll container). However, if there was a previously-snapped snap position (associated with the same element) that still exists after such changes, the UA must remain snapped to it—even if the changes would have placed a different snap position closer to the current scroll offset. Otherwise, the scroll container must be re-snapped as if the user had scrolled to its current scroll offset (as an explicit scroll, if no other scroll operation is active).

Clarification: Corresponding Dimensions Merged
  Clarify that percentages are calculated with respect to their corresponding dimensions.

  > Name: | scroll-snap-padding
  > Percentages: | relative to the corresponding dimension of the scroll container’s visual viewport

Fix Animatable Lines Merged
  Fix the Animatable lines

  > Name: | scroll-snap-padding
  > Animatable: | yes as length, percentage, or calc

  > Name: | scroll-snap-margin
  > Name: | yes as length

Defining the Scroll Snap Area Merged
  This wording explicitly hooks into the way `margin` and `border-image-outset` are defined, which ensures that the assignment of values is fully defined (by reference). It also clarifies that the bounding box is axis-aligned in the scroll container’s coordinate space.

  > The <length> values give outsets (interpreted as for margin or border-image-outset). The scroll snap area is the rectangular bounding box of the transformed border box, plus the specified outsets, axis-aligned in the scroll container’s coordinate space.

  > <length>{1,4}
  >   Specifies the outset of the element’s snap margin from the axis-aligned bounding box of the transformed border box, in the scroll container’s coordinate space. Outsets are applied to this bounding box, not the border box.

Definition of `scroll-snap-align` Merged
  The following definition is more concise and more concrete, because it hooks into the proper terminology.

  > The scroll-snap-align property specifies how an element’s scroll snap margin should align with its ancestor scroll container’s snapport the box’s snap position as an alignment of its snap area (as the alignment subject) within its snap container’s snapport as the alignment container).

Alignment Axes
  Tab and I intentionally used the logical axes for `scroll-snap-align` in the proposal we prepared for the WG. See further explanation. The following changes are due to this difference:

  > The two values specify the snapping behavior in the x block and y inline axes, respectively.

  > For all of these values, the block or inline axis is relative to the element’s parent’s writing mode.

Descriptive Subheadings Merged
  Tab and I try to use the subheadings as a way of describing what happens, preferably using words other than those that appear in the property name itself. We feel this helps people find the section they are looking for and better understand the concept represented in the section. The following changes bring the subheadings in line with this style. (We're open to alternative wording.)
  - Capturing Scroll Snap Areas: Properties on the scroll container
  - Scroll Snap Types Snapping Rules: the `scroll-snap-type` property
  - Scroll Snap Padding Snapping Window: the `scroll-snap-padding` property
  - Aligning Scroll Snap Areas: Properties on the element
  - Scroll Snap Margin Snapping Area: the `scroll-snap-margin` property
  - Scroll Snap Snapping Alignment: the `scroll-snap-align` property
Inlining Definitions Merged
  While having a glossary appendix is sometimes nice, Tab and I tend to put the defining instance of terms inline in the prose: either in the prose description of the model, or in the description of the property that defines exactly how the term works. In some ways this is a stylistic preference, but it has some concrete advantages:
  - It keeps normative prose defining a concept all in one place, so that by landing on the term definition it can be understood completely.
  - It avoids repetition, and thus the definitions going out-of-sync and conflicting with each other—as demonstrated here, where the (normative) definition of “snap margin” fails to account for fragmentation or transforms.
  We therefore recommend folding these definitions back into the prose. The following changes implement this:
  - Shift `<dfn>` markup for “snap position” back to the first paragraph of the overview and delete the (redundant) definition from the definition list:

    > This module introduces control over scroll snap positions, which are scroll positions that produce particular alignments of content within a scrollable viewport. Using the scroll-snap-type property n the relevant scroll container, the author can request a particular bias for the viewport to land on a valid 2 snap position after scrolling operations.

    > snap position
    >   For a scroll container, a particular value for its scroll offset is a snap position if when scrolled to that offset the visual viewport of the scroll container would align with a descendent element in the manner specified by the scroll snap properties.

  - Likewise, remove the definitions for the “snap area” and “snapport” and instead make their defining instance the ones in `scroll-snap-margin` and `scroll-snap-padding`, respectively:

    > snap alignment container
    >   A scroll container’s snap alignment container is the rectangle obtained by reducing its visual viewport by its scroll-snap-padding. ISSUE: better name for this concept?
    > snap margin
    >   An element’s snap margin is the rectangle obtained by expanding its border box by its scroll-snap-margin.

  - Shift the definition of “snapping” up into the Overview:

    > The act of adjusting the scroll offset of a scroll container’s visual viewport such that it is aligned to a snap position is called snapping, and a scroll container is said to be snapped to a snap position if its visual viewport’s scroll offset is that snap position and there is no active scrolling operation.

    > snapped
    >   A scroll container is said to be snapped to a snap position if its visual viewport’s scroll offset is that snap position and there is no active scrolling operation.
    > snap
    >   The act of adjusting the scroll offset of a scroll container’s visual viewport such that it is snapped to a snap position is called snapping.

  - Work with editors of CSS Overflow to define “scroll container” or an equivalent term and link to that. (Currently the ED of CSS Overflow Level 3 defines “scrollable box” as a term. This could be changed to “scroll container” or “scrollable container” if desired.)
  Note: In order to preserve readability of the spec top-to-bottom, we generally provide a parenthetical gloss of a term up front if it is used before its defining instance. In this spec, this is provided in the Overview section:

  > Snap positions are specified as a particular alignment (scroll-snap-align) of an element’s scroll snap area (its border box, as modified by scroll-snap-margin) within the scroll container’s snapport (its visual viewport, as reduced by scroll-snap-padding). This is conceptually equivalent to specifying the alignment of an alignment subject within an alignment container. A scroll position that satisfies the specified alignment is a valid snap position.

Rewordings
  The following rewordings are recommended, as they seem somewhat less awkward than the original wording:
  - Merged This rewording is less grammatically complex, and maintains parallelism with the previous parenthetical.

    > Snap positions can be specified as a particular alignment (`scroll-snap-align`) of an element’s scroll snap area (its border bounding box, as modified by `scroll-snap-margin`) within the scroll container’s snapport (the rectangle obtained by reducing its visual viewport its visual viewport, as reduced by its scroll-snap-padding).

  - Merged This one drops the (in CSS specs) unnecessary “must”, and shifts the parenthetical to the end so it doesn't interrupt the connection between the adjective “nearest ancestor” and the noun it describes.

    > Snap positions must only affect the nearest ancestor (on the element’scontaining block chain) scroll container on the element’scontaining block chain.

  - This rewording maintains parallel structure with the equivalent sentence in the definition for `proximity` (the concerns about reachability apply to equally to `proximity`, and are therefore handled in the general requirements for “snap positions”):

    > the scroll container is required to be snapped to a valid snap position when there are no active scrolling operations. If a reachable snap position exists, then the scroll container must snap at the termination of a scroll. That is, it must snap to a valid snap position at the termination of a scroll, if any exist.

    Adding parentheses to the following sentence (and simplifying it by using a pronoun) helps the reader to know that this case is considered exceptional:

    > (If no reachable snap position none exists, then no snapping occurs.)

  - Merged This rewording is more concise, but conveys the same thing.

    > The scroll-snap-padding property defines the scroll snapport—a region inset from the visual viewport of a scroll container used in calculating its snap positions. The snapport is used as the alignment container when calculating snap positions. the area of the scrollport that is used as the alignment container of the scroll snap areas when calculating their snap positions.

  - Merged The definition here is essentially redundant with the previous paragraph; Tab and I think this bit of text therefore doesn't need to exist.

    > [ <length> | <percentage> ]{1,4}
    >   Specifies the region inset from the visual viewport. Values are interpreted as for padding, and specify inward offsets from each edge of the visual viewport.

  - Merged This rewording is more concise, but conveys the same thing with as much precision.

    > The scroll-snap-margin property defines the scroll snap area on elements within a scroll container, used in calculating snap positions for that scroll container that is used for snapping this box to the snapport.

  - Merged This rewording uses terminology previously defined in order to present more concise definitions with simpler sentence structure:

    > Values are defined as follows:

    > none
    >   This box does not define a snap position in the specified axis.
    > start
    >   The scroll offset which aligns the start edge of this box’s scroll snap margin with the start edge of its ancestor scroll container’s region defined by scroll-snap-padding in the specified axis is a snap position in that axis.
    >   Start alignment of this box’s scroll snap area within the scroll container’s snapport is a valid snap position in the specified axis.
    > end
    >   The scroll offset which aligns the end edge of this box’s scroll snap margin with the end edge of its ancestor scroll container’s region defined by scroll-snap-padding in the specified axis is a snap position in that axis.
    >   End alignment of this box’s scroll snap area within the scroll container’s snapport is a valid snap position in the specified axis.
    > center
    >   The scroll offset which aligns the center of this box’s scroll snap margin with the center of its ancestor scroll container’s region defined by scroll-snap-padding in the specified axis is a snap position in that axis.
    >   Center alignment of this box’s scroll snap area within the scroll container’s snapport is a valid snap position in the specified axis.

Clarifying Additions
  The following insertions, we believe, clarify the text:
  - Since the model of snap positions is founded on the concept of “valid” and “invalid” scrolled views, this rephrasing helps to explain `scroll-snap-type: none` in that mental model:

    > &hellip the scroll container must not snap: all scroll positions are equally valid.

  - Merged This phrase provides something a little more concrete for the reader to relate to, making it less necessary for a casual reader to follow the definition link for “snap” to figure out what that means:

    > … the scroll container may snap to a valid snap position at the termination of a scroll …

    > … the scroll container is guaranteed to be snapped to a valid snap position when there are no active scrolling operations …

  - Merged This comma breaks up a very long string of (4) prepositional phrases by splitting off the UA discretion part:

    > the scroll container may snap to a valid snap position at the termination of a scroll, at the discretion of the UA given the parameters of the scroll.

Point Snapping Merged
  While Tab and I can accept for point-snapping to be deferred to the next level, we would like for at least the next (fully complete) publication to include this feature in its definition, for archiving (and future discussion). Our copy therefore includes definitions for the `point` value, as well as a section about how it works. (This is, as you can see, clearly labelled as “to be deferred”, however.)

  > Name: | scroll-snap-type
  > Value | none | [ proximity | mandatory ] || [ x | y | block | inline | both | point ]

  > point
  >   The scroll container point-snaps to snap positions in both axises simultaneously, treating each element’s snap position as a single 2D position (rather than potentially snapping to different elements in each axis).

  > ### 7.2. Axis vs Point-Snapping

  > This feature is planned to be removed in the next publication in order to reduce the feature-set of Level 1. It is included here for future reference in defining Level 2.

  > …

  (A likely use case for point snapping is tiled galleries that do not form a strict grid, as in this example (Flexbox) or this one (Grid). Again, we're happy to leave this to level 2, but do want the feature design published for future reference.)

Acknowledgements Update Merged
  We've added a list of the people who have contributed the spec, and noted that their proposals were mostly accepted rather than mostly ignored.

  > Many thanks to lots of people for their proposals and recommendations, some of which are incorporated into this document. David Baron, Simon Fraser, Håkon Wium Lie, Theresa O'Connor, François Remy, Majid Valpour, potentially some anonymous Microsoft engineers (?), and most especially to Robert O'Callahan for their proposals and recommendations, which have been incorporated into this document.

> Anyway, here is some feedback about the new draft. I hope it's not ignored again.