Gecko:CSSScrollSnapping: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Proposal ==
== Proposal ==


<tt>scroll-snap-vertical: none | proximity | mandatory</tt>
<tt>scroll-snap-type: none | proximity | mandatory</tt> (shorthand setting both x and y)


<tt>scroll-snap-horizontal: none | proximity | mandatory</tt>
<tt>scroll-snap-type-y: none | proximity | mandatory</tt>


<tt>scroll-snap: none | proximity | mandatory</tt> (shorthand setting both vertical and horizontal)
<tt>scroll-snap-type-x: none | proximity | mandatory</tt>


These properties apply to scrollable elements. Values are defined similar to the Microsoft [http://msdn.microsoft.com/en-us/library/ie/hh772038%28v=vs.85%29.aspx scroll-snap-type] property. The default value is "none".
These properties apply to scrollable elements. Values are defined similar to the Microsoft [http://msdn.microsoft.com/en-us/library/ie/hh772038%28v=vs.85%29.aspx scroll-snap-type] property. The default value is "none".
Line 11: Line 11:
A scrollable element is one for which 'overflow-x' or 'overflow-y' is 'scroll' or 'auto'.
A scrollable element is one for which 'overflow-x' or 'overflow-y' is 'scroll' or 'auto'.


<tt>scroll-snap-edge: none | [ margin-left || margin-start || margin-top || left || start || top ]</tt>
<tt>scroll-snap-edges: none | margin-box | border-box | center</tt>


This property defines which (if any) edges of the first CSS box for the element contribute to the allowable snapping positions for the nearest scrollable ancestor.
This property defines which (if any) CSS boxes for the element contribute to the allowable snapping positions for the nearest scrollable ancestor.


For an element E with 'scroll-snap-vertical' not 'none', the set of ''vertical snapping positions'' is the union of
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' contains 'margin-top', the top edge of the first margin-box of D if there is one.
* 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' contains 'top', the to edge of the first border-box of D if there is one.
* 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.


For an element E with 'scroll-snap-horizontal' not 'none', the set of ''horizontal snapping positions'' is the union of
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.
* For each descendant D of E for which E is the nearest scrollable ancestor, where D's value of 'scroll-snap-edge' contains 'margin-left', the left edge of the first margin-box of D if there is one.
* For each descendant D of E for which E is the nearest scrollable ancestor, where D's value of 'scroll-snap-edge' contains 'left', the left edge of the first border-box of D if there is one.


Transformation of a box edge up to the coordinate space of the scrollable element takes into account CSS positioning but not CSS transforms (so the orientation of the edge is guaranteed to be preserved).
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.


When scrolling an element with 'scroll-snap-vertical:mandatory' using selected UA scrolling mechanisms, the vertical offset gravitates to one of the vertical snapping positions at the end of the scrolling gesture. If the set of vertical snapping positions is empty, the vertical offset gravitates to zero.
UAs should apply scroll snapping to all user scroll gestures (including keyboard, scrollbars, etc). Script-driven scrolling (e.g. setting <tt>scrollLeft</tt> or <tt>scrollTop</tt>) 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.
 
When scrolling an element with 'scroll-snap-vertical:proximity' using selected UA scrolling mechanisms, the vertical offset gravitates to one of the vertical snapping positions at the end of the scrolling gesture, if it's "sufficiently close" to a snapping position.
 
Similarly for 'scroll-snap-horizontal'.
 
UAs can decide which scrolling mechanisms are subject to scroll snapping. For example, a UA might apply scroll snapping to touch-based panning and keyboard-driven scrolling but not scrollbar thumb dragging. Script-driven scrolling (e.g. setting <tt>scrollLeft</tt> or <tt>scrollTop</tt>) is never affected by scroll snapping.
 
The details of snapping behavior (physics) are up to the UA.

Latest revision as of 22:15, 4 March 2014

Proposal

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.