Skip to main content

Bug Tracker

Side navigation

#14515 closed feature (notabug)

Opened November 05, 2013 12:04PM UTC

Closed February 25, 2014 02:02PM UTC

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})
Attachments (0)
Change History (11)

Changed November 10, 2013 07:04PM UTC by dmethvin comment:1

owner: → 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.

Changed November 13, 2013 11:45AM UTC by robin@reala.net comment:2

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.

Changed November 13, 2013 01:46PM UTC by dmethvin comment:3

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

Changed November 15, 2013 05:25PM UTC by jzaefferer comment:4

owner: jzaefferer
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.

Changed November 15, 2013 05:59PM UTC by dmethvin comment:5

That sounds fine, can you file a docs issue?

Changed December 06, 2013 05:40PM UTC by timmywil comment:6

resolution: → notabug
status: newclosed

Changed January 13, 2014 11:26AM UTC by jzaefferer comment:7

Changed January 28, 2014 10:51AM UTC by jzaefferer comment:8

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?

Changed January 28, 2014 01:42PM UTC by kswedberg comment:9

@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.

Changed January 28, 2014 06:39PM UTC by dmethvin comment:10

status: reopenedopen

Changed February 25, 2014 02:02PM UTC by dmethvin comment:11

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.