scroll-snap-type: none | proximity | mandatory (shorthand setting both x and y)
scroll-snap-type-y: none | proximity | mandatory
scroll-snap-type-x: none | proximity | mandatory
These properties apply to scrollable elements. Values are defined similar to the Microsoft scroll-snap-type property. The default value is "none".
A scrollable element is one for which 'overflow-x' or 'overflow-y' is 'scroll' or 'auto'.
scroll-snap-edges: none | margin-box | border-box | center
This property defines which (if any) CSS boxes for the element contribute to the allowable snapping positions for the nearest scrollable ancestor.
Scroll snapping is applied at the end of each complete scroll gesture (e.g. after releasing the finger at the end of a touch panning gesture, after pressing an arrow key) to potentially adjust the final scroll destination. At the end of a scroll gesture which scrolls an element E, the UA determines a set of potential snapping opportunities:
- For each descendant D of E for which E is the nearest scrollable ancestor, where D's value of 'scroll-snap-edge' is 'margin-box', let B be D's first fragment's margin-box. If B exists, then each edge of B can be snapped to the corresponding edge of E's scroll-port.
- For each descendant D of E for which E is the nearest scrollable ancestor, where D's value of 'scroll-snap-edge' is 'border-box', let B be D's first fragment's border-box. If B exists, then each edge of B can be snapped to the corresponding edge of E's scroll-port.
- For each descendant D of E for which E is the nearest scrollable ancestor, where D's value of 'scroll-snap-edge' is 'center', let B be D's first fragment's border-box. If B exists, then the center of B can be snapped to the center of E's scroll-port.
These definitions implicitly require transforming a box rectangle up to the coordinate space of the element E. When CSS transforms are present, preserve axis-alignment by using the smallest axis-aligned rectangle that contains the transformed box.
The algorithm for computing which snapping opportunity (if any) to take is gesture and UA dependent. However the following constraints must be honored:
- If the scroll gesture has a definite direction (this is UA-dependent, but it includes clicking on scrollbar buttons or pressing up/down keys), the UA must not choose a snapping opportunity that makes the gesture result in scrolling in the opposite direction.
- When scrolling along an axis for which 'scroll-snap-type' is 'mandatory', the UA must choose one of the snapping opportunities for that axis (if there are any valid opportunities, subject to the previous requirement). However this requirement is lifted if one or more of the snapping opportunities' boxes B is larger than the scroll-port.
- When 'scroll-snap-type' is 'none' for some axis, no scroll snapping occurs along that axis.
UAs should apply scroll snapping to all user scroll gestures (including keyboard, scrollbars, etc). Script-driven scrolling (e.g. setting scrollLeft or scrollTop) is never affected by scroll snapping. Layout changes that affect the positions of elements with 'scroll-snap-edges', or dynamic changes to values of 'scroll-snap-edges', do not trigger snapping in the absence of a scroll gesture, even if 'mandatory' snapping is requested.