102

I'm trying to scroll down 100px every time the user gets near the top of the document.

I have the function executing when the user gets close to the top of the document, but the .scrollTo function isn't working.

I put an alert after and before to check to see if it actually was the line or not that was stopping it and only the first alert goes off, here's the code:

alert("starting");
$.scrollTo({ top: '+=100px', left: '+=0px' }, 800);
alert("finished");

I know I have the jquery page linked properly because I'm using many other jquery functions throughout and they all work fine. I've also tried removing the 'px' from above and it doesn't seem to make a difference.

  • 3
    Jquery itself my be working fine, but are you sure you have the scrollTo plugin linked properly? Change one of those alerts to alert($.scrollTo); – Andrew May 07 '09 at 05:03

6 Answers6

327
$('html, body').animate({scrollTop: $("#page").offset().top}, 2000);
bdukes
  • 152,002
  • 23
  • 148
  • 175
Mihai
  • 3,302
  • 2
  • 14
  • 3
  • 19
    I've often wondered why people use 'html, body' for scrollTop instead of just 'html'. Any thoughts on this? – Scott Greenfield Oct 27 '11 at 22:43
  • +1 worked for me ;) I also am interested to know why `html, body` instead of just html? – Kato Nov 09 '11 at 23:29
  • 10
    @ScottGreenfield, @Kato: not sure why, but this comment says not including `body` breaks this on Chrome 4: http://stackoverflow.com/questions/1890995/jquery-scroll-to-bottom-of-page-iframe – Yuji 'Tomita' Tomita Dec 20 '11 at 08:13
  • `scrollTop: 0` is also working fine. But duration goes down. Works fine if set 1000 in speed – shashwat Apr 22 '12 at 12:05
  • This is a good solution until you want to add a complete method - it will execute twice. @complistic 's solution is more elegant, and will prevent that. – plankguy Apr 20 '16 at 19:00
  • in IE with DTD 4 you need change `scrollTop` of `document.documentElement` (html) in other browsers you need to change `scrollTop` of `document.body` (body) - to make it work for all browsers you just change both via `$('html, body')` – Andi Jun 02 '17 at 11:37
  • I was having issues with this on certain browsers, mainly IE, and the issue was that my selector was only targeting `body`, adding `html, body` fixed it. – Daniel Dewhurst Jul 24 '17 at 13:23
  • FYI mobile safari uses `body` instead of `html`. – frodo2975 Feb 15 '20 at 05:37
98

If it's not working why don't you try using jQuery's scrollTop method?

$("#id").scrollTop($("#id").scrollTop() + 100);

If you're looking to scroll smoothly you could use basic javascript setTimeout/setInterval function to make it scroll in increments of 1px over a set length of time.

Fermin
  • 34,961
  • 21
  • 83
  • 129
  • 8
    Note if you want to scroll the whole page and not individual element, use $('html, body') just like [Tim](http://stackoverflow.com/users/181971) has pointed here. Just $('body') will not work in all browsers. – i-- Mar 28 '13 at 21:28
41

jQuery now supports scrollTop as an animation variable.

$("#id").animate({"scrollTop": $("#id").scrollTop() + 100});

You no longer need to setTimeout/setInterval to scroll smoothly.

Ish
  • 28,486
  • 11
  • 60
  • 77
Todd
  • 618
  • 5
  • 6
15

To get around the html vs body issue, I fixed this by not animating the css directly but rather calling window.scrollTo(); on each step:

$({myScrollTop:window.pageYOffset}).animate({myScrollTop:300}, {
  duration: 600,
  easing: 'swing',
  step: function(val) {
    window.scrollTo(0, val);
  }
});

This works nicely without any refresh gotchas as it's using cross-browser JavaScript.

Have a look at http://james.padolsey.com/javascript/fun-with-jquerys-animate/ for more information on what you can do with jQuery's animate function.

complistic
  • 2,610
  • 1
  • 29
  • 37
  • 1
    This is brilliant. I only changed `window.pageYOffset` to `$(window).scrollTop()` and `window.scrollTo(0, val)` to `$(window).scrollTop(val)` so I don't have to worry about browser compatibility. – leftclickben Sep 30 '14 at 17:01
  • 1
    I never thought to pass an object to jQuery's animate method like that. So many possible uses. This solution is great, thank you. – Synexis Dec 09 '14 at 11:21
  • Yes, technique is a significant contribution. Previously got around browser issues by using "window.scrollTo()" directly, but that doesn't allow for a "complete" call-back, nor a promise. Thank you @complistic for this solution. Also, my thanks to @leftclickben; I implemented his variation using ".scrollTop()". Also, the "james.padolsey" article, per link, is a terse, very worthwhile read. – IAM_AL_X Nov 04 '18 at 05:49
  • I think that "window.scrollTo()" should be compatible with all modern browsers. – IAM_AL_X Nov 04 '18 at 05:56
7

Looks like you've got the syntax slightly wrong... I'm assuming based on your code that you're trying to scroll down 100px in 800ms, if so then this works (using scrollTo 1.4.1):

$.scrollTo('+=100px', 800, { axis:'y' });
Alconja
  • 14,834
  • 3
  • 60
  • 61
6

Actually something like

function scrollTo(prop){
    $('html,body').animate({scrollTop: $("#"+prop).offset().top +
 parseInt($("#"+prop).css('padding-top'),10) },'slow');
}

will work nicely and support padding. You can also support margins easily - for completion see below

function scrollTo(prop){
    $('html,body').animate({scrollTop: $("#"+prop).offset().top 
+ parseInt($("#"+prop).css('padding-top'),10) 
+ parseInt($("#"+prop).css('margin-top'),10) +},'slow');
}
Tim
  • 2,466
  • 1
  • 21
  • 18