Gecko:CSSScrollSnapping: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
 
(2 intermediate revisions by the same user not shown)
Line 13: Line 13:
<tt>scroll-snap-edges: none | margin-box | border-box | center</tt>
<tt>scroll-snap-edges: none | margin-box | border-box | center</tt>


This property defines which (if any) CSS boxes for the element contribute to the allowable snapping positions for the nearest scrollable ancestor. Which edge of the box is used depends on the direction of the scroll operation. For example, when scrolling down, the bottom edge of the box should align with the bottom edge of the scrolling container. More details below.
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. The vocabulary of scroll gestures, and their scrolling behaviors (e.g. animation physics) depends on UA considerations and is not (and should not be) defined here. However, we require each gesture to have, for each axis, an *optional* direction; i.e. the horizontal direction can be "left", "right" or "unspecified", and the vertical direction can be "up", "down" or "unspecified". We also require each gesture to have an associated "start scroll position", which may or may not correspond to the actual scroll position at the start of the gesture. (E.g., if the user presses page-down twice quickly, the start position for the second page-down gesture may be the expected final destination of the first page-down gesture, even if the scrolling for that gesture hasn't completed yet.)
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:
 
At the end of a 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 '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 '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 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. These transformations must take into account CSS positioning but not CSS transforms (so the orientation of boxes is guaranteed to be preserved).
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.


Exactly which snapping opportunity (if any) is taken is UA-dependent, but subject to the following constraints:
The algorithm for computing which snapping opportunity (if any) to take is gesture and UA dependent. However the following constraints must be honored:
* If 'scroll-snap-type-x' is 'none', no snapping occurs in the horizontal direction.
* 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.
* If there are no snapping opportunities, no snapping occurs in the horizontal 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.
* If the gesture's horizontal direction is not "unspecified" and there are no snapping opportunities in the direction of the gesture, searching from the scroll position at the start of the gesture, no snapping occurs in the horizontal direction. (I.e. scroll snapping can't scroll in the opposite direction when a gesture has a definite direction.)
* When 'scroll-snap-type' is 'none' for some axis, no scroll snapping occurs along that axis.
* If the gesture's horizontal direction is "left", snapping opportunities that align the right edges of fragment boxes are ignored.
* If the gesture's horizontal direction is "right", snapping opportunities that align the left edges of fragment boxes are ignored.
* If 'scroll-snap-type-x' is 'mandatory', and none of the above constraints apply, snapping must occur in the horizontal direction.
Similar constraints apply in the vertical direction. When a snapping opportunity is taken, the UA applies additional scrolling to achieve the alignment specified by the snapping opportunity.


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.
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.
''It would be nice to have 'scroll-snap-type:mandatory' ensure that at all times we're scrolled to the snap-edge of some element, even after arbitrary content and style changes. However, it's not clear how that should behave in many cases. For example, without a scroll gesture direction, it's not clear whether you should snap the top of an element to the top of the container or the bottom of an element to the bottom of the container.''

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.