Skip to content

[css-scroll-snap-1] re-snapping after layout with animations #4609

Closed

Description

@majido

Context

The specification requires the browsers to re-snap after any content/layout changes. It also prefers re-snapping to the same element as before but if that element never existed or no longer exists then snapping to a new element is done.

We have been implementing this in Chrome and noticed an interesting implication of this: if one adds a single snap area to an existing snap container with no snap area, the container has to snap to the area.

This introduces an interesting new way to do "scroll-into-view" effects using only css. For example see this demo where I make the :active element to be a snap area which forces its ancestor scroller to re-snap which centers the element. I think this is interesting usecase of scroll-snap. However one limitation of this is that at the moment these re-snapping effects are not necessarily animated so the re-snap is jarring. Also webdevs don't have any control on such animations if we add them. I like to see if we can rectify this by making it animated but also exposing more control over such snap animations to web-devs.

Current Chrome Behavior

In Chrome we have decided to not animate layout-induced re-snapping in general. I think this makes sense in most re-snapping cases where we are re-snapping to the same element and the scroll snapping effect should not really be noticed by the user. But when we are re-snapping to a different element I think we should consider allowing animations.

The specification leaves it up to user agent whether to animate or not animate any particular snap operations. So we could just animate these in Chrome and I plan to experiment with this. At the same time I think it makes sense to give web authors control on the animation aspect of scroll-snapping since in some usecases they may not want any animations. Below I suggest one proposal to do this.

Proposal

We already have scroll-behavior to control programmatic scroll animations. So a simple solution is to have its definition expanded to control any scroll snap animation as a result of CSSOM scrolling APIs or re-snapping.

So the proposal suggestion has two parts:

A) Continue to leave animation decision up to user-agent but add a note that suggest user agent should consider animating when re-snap to different element.

B) Specify that scroll-behavior controls any scroll-snap animations that are not initiated by user. (This includes any CSSOM scrolling APIs that snap which I think they already did, and more importantly any animations that is introduced due to re-snapping)

Here is btw is the current wording for scroll-behavior:

The scroll-behavior property specifies the scrolling behavior for a scrolling box, when scrolling happens due to navigation or CSSOM scrolling APIs. Any other scrolls, e.g. those that are performed by the user, are not affected by this property. When this property is specified on the root element, it applies to the viewport instead.

Activity

  1. assigned and unassigned on Dec 16, 2019
  2. fantasai commented on Jan 16, 2020

    @fantasai
    Collaborator

    Interesting point!

    So I think the actions we should take to accept your proposal are:

    • rework the wording to make these two cases a little more distinct, so that they can be thought of as separate cases with some terminology to be able to reference them
    • recommend no animation in the "didn't change elements" case, to help anchor the view on it
    • suggest that the "snapped to a new element" case be treated scrolling-wise the same way as navigating to that element some other way, such as using .scrollIntoView() or .focus()), and should be subject to scroll-behavior accordingly
    • clarify the definition of scroll-behavior to match the above
  3. css-meeting-bot commented on Jan 22, 2020

    @css-meeting-bot
    Member

    The CSS Working Group just discussed re-snapping after layout with animations, and agreed to the following:

    • RESOLVED: Require smooth scrolling behavior when there is a new snap, but let UA decide when it's re-snapping to the same element.
    The full IRC log of that discussion <heycam> Topic: re-snapping after layout with animations
    <heycam> github: https://github.com//issues/4609
    <heycam> fantasai: re-snapping can be triggered in different cases
    <heycam> ... if you're snapped to an element, and the layout change
    <heycam> ... another one is a new snap position exists, or now you're in range of a snap position and you weren't before
    <heycam> ... scrolling is sometimes animated, sometimes not
    <heycam> ... there's a scroll-beahvior property that controls programmatic scroll animations
    <heycam> ... majid is saying that the scroll-behavior should probably also control the prgorammatic scroll behavior that's triggered by scroll snapping
    <heycam> ... and you might want to treat re-snapping to same elemetn differently from "not snapped, but not you're going to snap"
    <heycam> ... one proposal is to define that the snapped to a new element case be treated scrolling wise as the same as scrollIntoView() or focus()
    <heycam> ... and then therefore define that this should be subject to scroll-behavior
    <heycam> .. .the other thing w could do is to allow the UA do something different for the re-snap case
    <heycam> ... but in the case where you weren't snapped before, those cases should be animated in the same way scrollIntoView animates, and thus be subject to scroll-behavior
    <heycam> myles: why standardize this at all? why not say nothing?
    <heycam> TabAtkins: because Majid finds that the smooth scrolling behavior for the new snap position seems reasonable for the author to want to depend on
    <heycam> ... for the same reason scrolling to random things from JS be guaranteed smooth
    <heycam> fantasai: also clarifies interaction with scroll-behaviior
    <heycam> myles: how about the re-snapping behavior?
    <heycam> fantasai: I think we want to say something about it to make sure it's seen as distinct
    <heycam> ... we need to distinguish the re-snap case to be UA dependent so that scroll-behavior is not required to affect it
    <tantek_> as a user I may want a more responsive UI and set all the scroll behaviors to 'instant'
    <tantek_> like I want a way to turn-off cheesy animations
    <heycam> fantasai: don't feel the need to require not animating in that case, but should suggest it's possible
    <heycam> ... the goal of this re-snapping is to make the user feel that the layout changed but I didn't scroll
    <heycam> ... you don't want to animate to get back to where you were
    <heycam> myles: I think it depends how much of the viewport space the element takes up
    <heycam> ... if it's a small element, having most of what the user see jump to a different position would look jarring, but if the element covers most of the viewport, then jumping makes more sense
    <heycam> TabAtkins: that's reaosnable
    <heycam> ... as long as we distinguish it so that these cases are separate
    <fantasai> s/more sense/more sense. So would prefer may rather than should/
    <heycam> RESOLVED: Require smooth scrolling behavior when there is a new snap, but let UA decide when it's re-snapping to the same element.
  4. fantasai commented on Sep 17, 2020

    @fantasai
    Collaborator

    Added the following paragraph to the re-snapping section:

    Scrolling required by a re-snap operation to a new or different box must behave and animate the same way as any other scroll-into-view operation, including honoring controls such as 'scroll-behavior'. Scrolling behavior for re-snapping to the same box as before however, is UA-defined. The UA may, for example, when snapped to the start of a section, choose not to animation the scroll to the section’s new position as content is dynamically added earlier in the document in order to create the illusion of not scrolling.

    And made the following edits to 'scroll-behavior':

    The scroll-behavior property specifies the scrolling behavior for a scrolling box, when scrolling happens due to navigation, or CSSOM scrolling APIs, or scroll snapping operations not initiated by the user [[!CSS-SCROLL-SNAP-1]]. Any other scrolls, e.g. those that are performed by the user, are not affected by this property.

    @majido @tabatkins @smfr Lmk if the edits look good.

  5. majido commented on Oct 9, 2020

    @majido
    ContributorAuthor

    This edits lgtm and achieve the desired outcome. Thanks for the edit. /cc @flackr

  6. majido commented on Oct 9, 2020

    @majido
    ContributorAuthor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions