Opened 9 years ago
Closed 9 years ago
#14515 closed feature (notabug)
Normalize scrolling of document
Reported by: | jzaefferer | Owned by: | |
---|---|---|---|
Priority: | undecided | Milestone: | None |
Component: | unfiled | Version: | 1.10.2 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
A pretty common usecase I had to implement every now and then: A click on a in-page link should do an animated scroll, instead of just jumping to the target. This seems easy to do with jQuery (and can't be done with CSS Transitions, since CSS can't control scroll), but actually ends up in googling and copy/pasting some crappy solution from StackOverflow.
Eventually it'll end up with something like this:
$( "html, body" ).animate({ scrollTop: ... });
On the way I'll try to do $(document).scrollTop(...), since reading scroll from document via .scrollTop() usually works.
I'd like to see this addressed in jQuery (once and for all). In the end there should be only one element that is valid to read and write its scrollTop to "scroll to the page". I don't care if that is document, html or body, though I think only document and body are valid choices. But this choice should be made once, by standards or jQuery, if there are no standards covering this. The documentation for http://api.jquery.com/scrollTop/ should document how to do this then.
Maybe any attempt to do it the wrong way can be deprecated and throw a warning when using the Migrate plugin. Throwing an actual error is probably not possible due to backwards compat.
Related bug report from Krinkle on this isssue happening on Wikipedia: https://bugzilla.wikimedia.org/show_bug.cgi?id=54928#c1
According to him, this is the way to go, as it actually works:
$(document.body).animate({'scrollTop': 100})
Change History (11)
comment:1 Changed 9 years ago by
Owner: | set to jzaefferer |
---|---|
Status: | new → pending |
comment:2 Changed 9 years ago by
The problem with $('html,body') is that if you set a callback it’ll fire twice, something that’s caught me out in the past.
comment:3 Changed 9 years ago by
@robin, use .then()
rather than a callback, it only fires once per animation rather than per element.
comment:4 Changed 9 years ago by
Owner: | jzaefferer deleted |
---|---|
Status: | pending → new |
How about adding something like this to the API docs for scrollTop()?
Note that scrollTop can be used to read, but not write, the document scroll position. To scroll the document, animated or not, you have to call {{{scrollTop()}} on the body element:
// Without animation $( document.body ).scrollTop( 500 ); // With animation $( document.body ).animate({ scrollTop: 500 });
Any examples elsewhere that suggest $( "html, body" ).animate({ scrollTop: ... });
are wrong, since this will cause the animation callback to get triggered twice.
I could then reference this myself in the future and point people to it. Maybe we can even outvote some bad SO answers.
comment:6 Changed 9 years ago by
Resolution: | → notabug |
---|---|
Status: | new → closed |
comment:7 Changed 9 years ago by
Created a docs issues: https://github.com/jquery/api.jquery.com/issues/417
comment:8 Changed 9 years ago by
Resolution: | notabug |
---|---|
Status: | closed → reopened |
I ran into this again and did some actual testing. The "solution" I referenced doesn't actually work. To scroll the document in Chrome, "body", has to be selected. To scroll the document in IE8, it has to be "html". That's why all the snippets use "html, body", even though that leads to the double callback.
Coming back to the original discussion, is this something jQuery can normalize?
comment:9 Changed 9 years ago by
@jzaefferer: it's kind of a pain to determine which element is "scrollable." I attempt it in one of my plugins: https://github.com/kswedberg/jquery-smooth-scroll/blob/master/src/jquery.smooth-scroll.js (Note, especially, lines 59–74).
That said, if there's a better way to do this, I'd love to hear it.
comment:10 Changed 9 years ago by
Status: | reopened → open |
---|
comment:11 Changed 9 years ago by
Resolution: | → notabug |
---|---|
Status: | open → closed |
It sounds like this isn't something we can normalize, and we have a docs ticket, so I'll close this.
So is the idea here to define the One True Way to scroll the document and then not try to normalize the others? We could certainly add something to Migrate but most people will have already noticed that using
window
,document
, or"html"
didn't work cross browser.Since
"html, body"
does work, I can see some people being annoyed that working code threw errors. Isn'tdocument.body
the same as"body"
?The intent here might be clearer with the actual code/documentation solution.