Bug Tracker

Opened 5 years ago

Closed 5 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:


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 5 years ago by dmethvin

Owner: set to jzaefferer
Status: newpending

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't document.body the same as "body"?

The intent here might be clearer with the actual code/documentation solution.

comment:2 Changed 5 years ago by robin@…

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 5 years ago by dmethvin

@robin, use .then() rather than a callback, it only fires once per animation rather than per element.

comment:4 Changed 5 years ago by jzaefferer

Owner: jzaefferer deleted
Status: pendingnew

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:5 Changed 5 years ago by dmethvin

That sounds fine, can you file a docs issue?

comment:6 Changed 5 years ago by timmywil

Resolution: notabug
Status: newclosed

comment:8 Changed 5 years ago by jzaefferer

Resolution: notabug
Status: closedreopened

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 5 years ago by kswedberg

@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 5 years ago by dmethvin

Status: reopenedopen

comment:11 Changed 5 years ago by dmethvin

Resolution: notabug
Status: openclosed

It sounds like this isn't something we can normalize, and we have a docs ticket, so I'll close this.

Note: See TracTickets for help on using tickets.