Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cssom-view] New feature - scroll-boundary-behavior (an extension of -ms-scroll-chaining) #769

Closed
majido opened this issue Nov 28, 2016 · 36 comments

Comments

@majido
Copy link
Contributor

majido commented Nov 28, 2016

We are proposing standardization of "-ms-scroll-chaining" with some modification. The details of the proposal can be found in this WICG where it is being incubated but here is the executive summary of proposed feature:

scroll-boundary-behavior: propagate | contain | none

  • propagate: propagate scroll to the parent scroller. If there is no parent scroller (e.g., viewport) user-agent may perform a default action (e.g. navigation) or show any appropriate overscroll UI affordance. This is the default value.
  • contain: do not propoagate. The user agent may show an appropriate overscroll UI affordance such as glow/bounce etc.
  • none: same as contain but also prevents any overscroll UI affordance e.g. bounce or glow.
    There will be scroll-boundary-behavior-{x,y} long-hands too.

Here are the differences compared to existing -ms-scroll-chaining which is fairly limited in functionality:

  1. Applies to all user scrolls (not just touch/touchpad)
  2. Per axis control (matching overflow-{x,y})
  3. Meaningful and useful definition of chaining behavior at viewport level
  4. Additional control over bounce/glow affordances

I think CSSOM View is probably the right spec to host this new attribute as it provides an API to control certain aspects of scrolling (similar to scroll-behavior in this respect).

There is some agreement on WICG that the proposed changes are reasonable and useful. So if you think this is the right spec to standardize I can start working on a pull request with appropriate changes to make the proposal more concrete. Any feedback on functionality and naming is also very welcome and appreciated.

@majido
Copy link
Contributor Author

majido commented Nov 28, 2016

/cc @zcorpan @ChumpChief

@zcorpan
Copy link
Member

zcorpan commented Nov 28, 2016

Personally I think this is a reasonable proposal and cssom-view seems like a good home for the feature.

The name of the property was brought up in the WICG thread. I don't have a strong opinion at this time.

The property IE/Edge support has been discussed in the context of Houdini:
https://lists.w3.org/Archives/Public/public-houdini/2016Feb/0010.html

esphren: If everyone always implemented -ms-scroll-chain:none
always, we wouldn't need the property.
@RByers: Well, might be nice to have the ability to bubble if you
wanted, but we removed it and no one complained.

Did someone complain? :-)

It would be good to have relevant people from Apple and Mozilla also, so we don't spec and ship something that they object to. cc @hober @dbaron

@majido
Copy link
Contributor Author

majido commented Nov 28, 2016

The property IE/Edge support has been discussed in the context of Houdini:
https://lists.w3.org/Archives/Public/public-houdini/2016Feb/0010.html

esphren: If everyone always implemented -ms-scroll-chain:none
always, we wouldn't need the property.
@RByers: Well, might be nice to have the ability to bubble if you
wanted, but we removed it and no one complained.

Did someone complain? :-)

I think at that point in time @RByers assumption was that -ms-scroll-chaining only applies during a single gesture and is not applicable at the beginning of the gesture. This is not correct.

Chrome has disabled chaining only during the gesture and I don't think we have any major complains there. However, it still does scroll chaining at the beginning of the gesture and I doubt very much if we ever want to disable that by default. This is the case that we see the most value for having an API that provides an escape hatch.

@majido
Copy link
Contributor Author

majido commented Dec 6, 2016

@hober @dbaron do you have any major objection to the propose direction?

We like to start implementing this in Blink behind a flag to gain experience with the feature so I appreciate any public signal you can provide.

@staktrace
Copy link

FWIW I think this is a reasonable proposal and it would give us a good way to fix bug 951793 in Firefox.

@dbaron
Copy link
Member

dbaron commented Dec 21, 2016

So from today's teleconference a number of points came up:

  • across multiple (but maybe not all?) engines, this decision is made not per-pixel-of-scrolling but per-scrolling-gesture. If that's true in all engines, maybe it should just be specified that way. If not, it needs to account for differences somehow
  • In Gecko at least, propagate is not the default behavior for keyboard scrolling. This should be tested as well. (But maybe it should be?)

So I think, at the very least, the initial value would need to have a better match for what today's behavior is, assuming we don't have a wide agreement to change the behavior.

There was also concern about the name of the propagate value (hard to spell) and the name of the property.

@zcorpan zcorpan removed the Agenda+ label Dec 22, 2016
@majido
Copy link
Contributor Author

majido commented Dec 22, 2016

Thanks for the feedback.

across multiple (but maybe not all?) engines, this decision is made not per-pixel-of-scrolling but per-scrolling-gesture. If that's true in all engines, maybe it should just be specified that way. If not, it needs to account for differences somehow.

We can actually leave when the decision is made unspecified and leave it up to UA implementation. I More below.

In Gecko at least, propagate is not the default behavior for keyboard scrolling. This should be tested as well. (But maybe it should be?)

I can confirm this is indeed the case in Gecko for keyboard (tested on Linux).

So I think, at the very least, the initial value would need to have a better match for what today's behavior is, assuming we don't have a wide agreement to change the behavior.

I think this is reasonable. I don't believe we need to have all UAs agree on which inputs and exactly when (per-pixel or per-gesture) they chain the scroll. All main usecases that need this feature actually care about a consistent method to prevent the default chaining as opposed to forcing chaining to happen for a particular input or at a particular time.

Here is one way we can spec this to achieve the above without taking away the UA flexibility in deciding when to chain.

  • Replace 'propagate' with 'auto'. So we don't prescribe what is the default boundary behavior and leave it up to UA. This also addresses the spelling concern with 'propagate'.
  • Keep 'none' and 'contain' as they are. They simply prevent the default behavior which is propagation.

@ChumpChief
Copy link
Member

+1 for auto | contain | none, good points made about other scrolling mechanisms. We also decline to propagate keyboard scrolling in Edge by design, and for other scrolling mechanisms it may be even less clear what forcing propagation should even mean (e.g. scrollbar, JS scrolling).

Also agreed the specifics of when to propagate don't need specification. Something like this should be fine: "UAs may elect to scroll an ancestor element when the targeted element has reached its boundary in the direction of the scroll. This ancestor scrolling behavior must be disabled by..."

@majido
Copy link
Contributor Author

majido commented Feb 14, 2017

If I am reading this correctly, it seems that there is enough consensus around the last proposed version of the API and its applicability. We are planning to start working on its implementation in Blink fairly soon. Perhaps, it is best to start a pull request to the spec to clarify the language and details.

BTW, in last BlinkOn conference, we had a chance to chat with some Facebook DevRel folks which mentioned they are very interested in this feature:

This would be fantastic for FB as it's the main thing blocking us from making the wheel event passive.

@bmaurer
Copy link

bmaurer commented Feb 14, 2017

Confirming that this is really important to FB. We can test this out pretty quickly once it's committed to Blink.

@zcorpan
Copy link
Member

zcorpan commented Feb 15, 2017

@majido yes a pull request sounds good to me, we can discuss in more detail then.

@dvoytenko
Copy link

We'd really like this in AMP as well.

@bgirard
Copy link
Contributor

bgirard commented Mar 24, 2017

There's a related proposal with a confusingly similar name 'overscroll-action':
https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/Uzit4zDQ1ps/pD_3k2rqBAAJ

overscroll-action applies to the gesture on the viewport for history navigation (2 finger swipe back on Mac) and pull-to-refresh.

I find the nomenclature a bit confusing because 'overscroll-action: auto' would suggest that the element would behave as if it had 'scroll-boundary-behavior: propagate' which is orthogonal.

  1. Should the two proposal be considered orthogonal? If so it allows over-scroll animations (glow/bounce) to be toggled independently from navigation gestures.
  2. If we consider the specifications to be orthogonal can we come up with better nomenclature? I would suggest that 'navigation-action' would be better name 'overscroll-action'.
  3. Right now it's not possible to propagate scrolling while disabling the overscroll animation. If this is something that's important perhaps a better proposal to cover the 4 logical states could be:
    scroll-boundary-behavior: [auto || [ [propagate || contain] | [overscroll || no-overscroll] ]
  4. Does 'overscroll-action-x: contain' behave as if 'overscroll-action: no-navigation-x' was set? From an implementation point of view I believe 'overscroll-action-x: contain' should behave as if the script was performing preventDefault on any overscroll and thus disallow events from reaching the viewport and thus would implicitly disallow overscroll (navigation) actions.

[edit] Corrected property name to scroll-boundary-behavior in 3)

@fantasai
Copy link
Collaborator

fantasai commented Mar 24, 2017

Agenda+ to discuss adding it to an actual spec draft. If this is something we want to add, we should have it in a draft somewhere and people can file issues on specifics.

@fantasai fantasai added the css-overflow-3 Current Work label Mar 24, 2017
@fantasai
Copy link
Collaborator

Also, since this is (afaict) a CSS property and not an OM feature, it probably belongs in css-overflow rather than cssom-view...

@flackr
Copy link
Contributor

flackr commented Mar 27, 2017

Agenda+ to discuss adding it to an actual spec draft. If this is something we want to add, we should have it in a draft somewhere and people can file issues on specifics.

We (@flackr, @majido, @RByers ) will be in Tokyo for the CSSWG meeting and would be happy to lead a session to get into details there if this would be helpful. We can draft up something after Tokyo F2F if that makes sense.

Also, since this is (afaict) a CSS property and not an OM feature, it probably belongs in css-overflow rather than cssom-view...

No particular opinion here. It will be great if we land on an answer here in next telecom. The original rationale for why cssom was in comment#1:

CSSOM View is probably the right spec to host this new attribute as it provides an API to control certain aspects of scrolling (similar to scroll-behavior in this respect).

There's a related proposal with a confusingly similar name 'overscroll-action':
https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/Uzit4zDQ1ps/pD_3k2rqBAAJ

I have chatted with @majido to ensure we are on the same page with regards to the overscroll-action vs scroll-boundary-behavior API:

overscroll-action applies to the gesture on the viewport for history navigation (2 finger swipe back on Mac) and pull-to-refresh.

A bit of history here, we developed overscroll-action API idea first in response to a specific set of overscroll navigation usecases. But now we think it is possible to address those use cases with scroll-boundary-behavior API in a simpler and more generic way.

I find the nomenclature a bit confusing because 'overscroll-action: auto' would suggest that the element would behave as if it had 'scroll-boundary-behavior: propagate' which is orthogonal.

  1. Should the two proposal be considered orthogonal? If so it allows over-scroll animations (glow/bounce) to be toggled independently from navigation gestures.

We should avoid having two different ways to control overscroll navigation actions. So if we allow scroll-boundary-behavior to control overscroll navigation then it is best to ditch overscroll-action.

Toggling overscroll animations independent from navigation gesture could be accomplished using the extended API you proposed in #3.

  1. If we consider the specifications to be orthogonal can we come up with better nomenclature? I would suggest that 'navigation-action' would be better name 'overscroll-action'.
  2. Right now it's not possible to propagate scrolling while disabling the overscroll animation. If this is something that's important perhaps a better proposal to cover the 4 logical states could be:
    scroll-boundary-behavior: [auto || [ [propagate || contain] | [overscroll || no-overscroll] ]

I think it’s best left to the UA’s discretion whether showing a bounce or glow makes sense when you are going to propagate the scroll. The intention of disabling it is to allow the author to control the containment case.

  1. Does 'overscroll-action-x: contain' behave as if 'overscroll-action: no-navigation-x' was set? From an implementation point of view I believe 'overscroll-action-x: contain' should behave as if the script was performing preventDefault on any overscroll and thus disallow events from reaching the viewport and thus would implicitly disallow overscroll (navigation) actions.

scroll-boundary-behavior-x: contain (I assume you meant scroll-boundary-behavior-x since contain is not a property of overscroll-action-x) does behave as if overscroll-action: no-navigation-x was set as the scroll does not propagate to the “default” browser behavior, e.g. this may be navigation, refresh, etc. This is equivalent to the script performing preventDefault on the additional events as you had suggested.

@ChumpChief
Copy link
Member

A bit of history here, we developed overscroll-action API idea first in response to a specific set of overscroll navigation usecases. But now we think it is possible to address those use cases with scroll-boundary-behavior API in a simpler and more generic way.

We should avoid having two different ways to control overscroll navigation actions. So if we allow scroll-boundary-behavior to control overscroll navigation then it is best to ditch overscroll-action.

Agreed. From the Edge perspective, any UA reactions to scrolls beyond the boundary (navigation, pull-to-refresh, Flip Ahead) are well-controlled by simply blocking the propagation of the scroll above the root scroller.

Right now it's not possible to propagate scrolling while disabling the overscroll animation. If this is something that's important perhaps a better proposal to cover the 4 logical states could be:
scroll-boundary-behavior: [auto || [ [propagate || contain] | [overscroll || no-overscroll] ]

I think this proposal should be [auto | contain] || [overscroll | no-overscroll] for the reasons David and Majid mentioned in the previous comments about input type discrepancies and spelling difficulty.

That said, I'm not aware of any implementation that propagates in combination with showing a visual effect of any sort. Implementation-wise this would be unusual since the transform from the input is "applied towards" a particular target. Visually to a user it would also look strange as the ancestor scrolls (or does some other effect) while the child displays an effect that is meant to signify "you can't scroll any further". When that effect is a bounce e.g. in response to touch panning it would result in the bounced content moving twice as fast as the user's finger (the transform being applied to both the element and its ancestor). I don't think that's a combination we should support.

Without that combination there are only 3 states, which map to the auto | contain | none values. I strongly prefer this option over providing 4 states.

@bmaurer
Copy link

bmaurer commented Mar 28, 2017 via email

@ChumpChief
Copy link
Member

I think it'd be reasonable for a UA to show a visual indication of overscroll on a contained scroll. Rather than showing a bounce on the ancestor which would indeed look weird you'd show it on the element that was over scrolled.

This is the contain value in the 3-state model. None of the values would result in a visual effect on an ancestor of an element that contained the scroll.

@bmaurer
Copy link

bmaurer commented Mar 28, 2017 via email

@ChumpChief
Copy link
Member

That would be the none value in the 3-state model. No visual effect, no propagation.

@astearns
Copy link
Member

The CSSWG resolved to work on this in a WICG repo for now, to test out the whole incubation process.

@astearns astearns removed the Agenda+ label Apr 10, 2017
@bgirard
Copy link
Contributor

bgirard commented Apr 19, 2017

The repo is now live:
https://github.com/WICG/scroll-boundary-behavior/issues

I've tried to summarize this discussion. All discussion is welcome in this repo. I'll start a spec draft in the repo after a bit more discussion (or lack of) has happened.

@bgirard
Copy link
Contributor

bgirard commented Apr 26, 2017

I've posted a draft here:
https://wicg.github.io/scroll-boundary-behavior/

Feedback is welcome

@majido
Copy link
Contributor Author

majido commented Sep 7, 2017

Our implementation is now in Canary behind a flag and you can test it (simple demo). Feedback and bug reports are very welcome.

As our implementation has matured we have been giving @bgirard feedback based on it. We feel confident enough with our implementation and the spec and thus are considering to ship it in Chrome M63.

What works:

  • On inner scrollers the property controls chaining behavior for touch/wheel inputs.
  • On Android, when used on viewport defining element, the property can control pull-to-refresh and overscroll glow behaviors.

Work that is still in progress:

  • Add support for controlling wheel swipe navigation for MacOS and ChromeOS.
  • Upstreaming our tests to web-platform-tests

Here are the bugs to follow for Firefox and WebKit.

@klimashkin
Copy link

@majido Thanks for Canary implementation! Tested.

But without scroll-boundary-behavior being able to prevent navigation on scroll-x in MacOS it's still not helpful for creating component of scrollable tabs, and we still have to workaround with preventDefault on mousewheel event.

Hope it will be possible by the time feature released!

@majido
Copy link
Contributor Author

majido commented Oct 12, 2017

@klimashkin this chromium bug tracks that particular feature. You can star that to follow our progress and leave specific comments there but current plan is to fix that for M64.

@majido
Copy link
Contributor Author

majido commented Oct 16, 2017

I filed for TAG review for this API and here is the full feedback.

One of the feedback items which I am not fully sure about is whether this should be part of the overflow property as opposed to being a new property. TAG was not really sure on either direction. Here is the actual feedback:

Should this be a new property, or should this be a new part of the value on 'overflow'? It wasn't clear to us which is the right thing; in CSS this is often decided by whether the pieces should cascade together or separately.

I am inclined to think it is best if this is a separate property i.e., the current design. I can imagine cases where one component want to control scroll-boundary-behavior but not the overflow e.g., to disable pull-to-refresh one should not need to mess with overflow, or a page that want to do * {scroll-boundary-behavior: contain} without changing overflow. Also I feel scroll-boundary-behavior play a similar role as scroll-behavior so it makes sense to match its behavior and be a separate property.

I provided a tentative response based on the above. However, if there is anyone here who has a strong opinion one way or another I love to hear it and will reflect that to TAG. Same goes for any other feedback item there.

@ChumpChief
Copy link
Member

I like your response and agree it should be a separate property from overflow.

@birtles
Copy link
Contributor

birtles commented Oct 16, 2017

As a non-US speller, a property name that doesn't include behavior would seem preferable. It's also a bit long. Is scroll-boundary not sufficient? It also has the advantage of being sufficiently different from the existing (and functionally unrelated) scroll-behavior. Or even scroll-overflow?

@ChumpChief
Copy link
Member

I'd argue this property is highly related to scroll-behavior, actually. Where scroll-behavior describes behavioral details of scrolling (e.g. modifying animations and physics), scroll-boundary-behavior describes behavioral details of scrolling at the boundary of the scroller (e.g. modifying animations and physics).

scroll-boundary (without "behavior") seems ambiguous to me - I would expect that to perhaps define the position of the boundary, or whether a boundary exists (vs. being an infinite scroller). Rather than what the UA will do when that boundary is reached.

I think other synonyms for "behavior" could potentially be fine, though I don't necessarily think there's anything wrong with that choice and I kind of like the parallel to scroll-behavior.

@birtles
Copy link
Contributor

birtles commented Oct 17, 2017

Those two things sound different to me and seem only related by the fact they have something to do with scroll. Furthermore, -behavior seems like a largely meaningless addition to a property name: just about any property could potentially add -behavior without it changing the meaning, e.g. overflow-behavior, display-behavior, visibility-behavior, etc.

With regards to the length, our experience with animation-timing-function suggests that a short memorable name, even if not completely accurate, is preferable to a long but technically accurate name (hence why Web Animations went with easing in place of timingFunction in the API). So I guess my vote is with scroll-overflow.

@bgirard
Copy link
Contributor

bgirard commented Oct 17, 2017

I think there's some good points here. But I would like to note that overflow: none is logical (there's no overflow), while scroll-boundary: none would mean that there's no scroll boundary which to me is illogical and inconsistent with scroll-boundary-behavior: none which is logical to me but maybe just because I've been looking at this for months now. Similarly for scroll-behavior: none.

Another example: display: none is logical while display-behavior: none is confusing. I think for that reason it's not that same as adding -behavior to existing properties. Is that argument convincing?

I do somewhat like scroll-overflow but I think scroll-boundary-behavior is more descriptive. I agree that a short memorable name can be preferable however.

I think a better place to discuss this would be under a new issue in the repo:
https://github.com/WICG/scroll-boundary-behavior

@tabatkins
Copy link
Member

I agree with Brian—"behavior", like "mode", is a zero-information word that should not be included in the property name. Most properties could have -behavior appended to them without changing meaning at all.

But yeah, we should move the discussion to the WICG. I'll close this issue. ^_^

@Link2Twenty
Copy link

I've noticed a small issue unless this is by design.

When you have a drawer that doesn't need scrolling, due to content size, it allows overscroll but I presume most people would want overscroll to still be blocked.

https://jsfiddle.net/link2twenty/75ceok4b/

@jonjohnjohnson
Copy link

jonjohnjohnson commented Feb 1, 2019

@Link2Twenty It's by design, though cross axis scrolling (not exactly overscroll effects) seems surely overlooked in the spec language. See #3349

But in your example, for the nav you could add overflow: auto (or scroll) to the nav element and this would enable a user scrollable scrolling mechanism. And since the nav is styled as position: fixed, your specific problem is remedied because the scroll chaining context now doesn't involve the document scroller. This however isn't a solution for other position schemes that do not alter the scroll chaining context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests