80

I have used a scrollTop function in jQuery for navigating to top, but strangely 'the smooth animated scroll' stopped working in Safari and Chrome (scrolling without smooth animation) after I made some changes.

But it is still working smoothly in Firefox. What could be wrong?

Here is the jQuery function I used,

jQuery:

$('a#gotop').click(function() {
    $("html").animate({ scrollTop: 0 }, "slow");
    //alert('Animation complete.');
    //return false;
});

HTML

<a id="gotop" href="#">Go Top </a>

CSS

#gotop {
      cursor: pointer;
      position: relative;
      float: right;
      right: 20px;
      /*top:0px;*/
}
Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
Maju
  • 1,195
  • 2
  • 9
  • 17
  • 1
    http://jsbin.com/erade/2 works fine on chrome – jAndy Jun 15 '10 at 05:32
  • @jAndy, I was wondering why `scrollTop`, which is not a valid css property, works on your demo?... can you share some info or link about it? – Reigel Gallarde Jun 15 '10 at 05:55
  • @Reigel: I have to admit, I can't. I use it pretty much like a blackbox, but jQuery infact normalizes it crossbrowser. – jAndy Jun 15 '10 at 06:04
  • @jAndy - okay... but I guess it would not be advisable to use `scrollTop` inside animate css map properties... I'm still digging though.. – Reigel Gallarde Jun 15 '10 at 06:18
  • Possible duplicate of [scrolltop with animate not working](https://stackoverflow.com/questions/18779708/scrolltop-with-animate-not-working) – Mister Q Jul 13 '18 at 14:17

16 Answers16

106

Try using $("html,body").animate({ scrollTop: 0 }, "slow");

This works for me in chrome.

Aaron Butacov
  • 32,415
  • 8
  • 47
  • 61
  • Yes.Thanks.Simple and timesaving. – Maju Jun 15 '10 at 06:19
  • I had exactly the same issue, although I was also animating scrollTop. the interesting thing is that $("html") works in FF, and $("body") works in Chrome/Safari, but only $("html,body") has worked for me in both. – Bryan Agee May 11 '11 at 20:49
  • 3
    This has a side effect: a callback function will be called twice (once for each element). Any smart workaround for this, anybody? – bububaba Mar 19 '12 at 08:19
  • 8
    Put: if (this.nodeName == "BODY") { return; } at the beginning of your callback function so only the callback from the html element will go through. Also, remember that the nodeName attribute on html elements is always uppercase. – Bobby Aug 15 '12 at 17:26
  • 1
    Thank you @Bobby for pointing this out! Extremely useful when using a callback function that one should fire once and work across all browsers! TA! – Sebastian Apr 12 '13 at 17:54
  • The bad side of this is that in Firefox, the callback method of animate will be called twice. Once for body and than for html :/ – Aamir Afridi May 10 '13 at 16:23
  • 1
    I had to use $("body,html") to work in all browsers. – Tom Kincaid Jul 12 '17 at 15:58
  • Sorry but I can't get it working in Chrome, I just want speed when scroll, do not execute anythig else, so I just put `jQuery.scrollSpeed(100, 800);` when "document ready", What do I have to do for working with chorme? Thanks – Albert Català Jul 24 '17 at 12:57
  • Just to add, than I have scroll on a div inside body, not in body – Albert Català Jul 24 '17 at 13:25
58

If your CSS html element has the following overflow markup, scrollTop will not function.

html {
    overflow-x: hidden;
    overflow-y: hidden;
}

To allow scrollTop to scroll, modify your markup remove overflow markup from the html element and append to a body element.

body { 
    overflow-x: hidden;
    overflow-y: hidden;
}
Tyler Rafferty
  • 3,391
  • 4
  • 28
  • 37
user2971963
  • 581
  • 4
  • 6
15

It works in both browsers if you use scrollTop() with 'document':

$(document).scrollTop();

...instead of 'html' or 'body'. Other way it won't work at the same time in both browsers.

Alejandro del Río
  • 3,966
  • 3
  • 33
  • 31
5

I have used this with success in Chrome, Firefox, and Safari. Haven't been able to test it in IE yet.

if($(document).scrollTop() !=0){
    $('html, body').animate({ scrollTop: 0 }, 'fast');
}

The reason for the "if" statement is to check if the user is all ready at the top of the site. If so, don't do the animation. That way we don't have to worry so much about screen resolution.

The reason I use $(document).scrollTop instead of ie. $('html,body') is cause Chrome always return 0 for some reason.

Universal Electricity
  • 775
  • 1
  • 12
  • 26
Steven
  • 59
  • 1
  • 1
4

I had a same problem with scrolling in chrome. So i removed this lines of codes from my style file.

html{height:100%;}
body{height:100%;}

Now i can play with scroll and it works:

var pos = 500;
$("html,body").animate({ scrollTop: pos }, "slow");
Ramin Bateni
  • 16,499
  • 9
  • 69
  • 98
  • Wow. This totally fixed my issue! I could not get scrollTop to work at all but once i removed height: 100% from the body and html element it worked great. Thank you, thank you, thank you. – agon024 Sep 06 '16 at 20:26
  • @agon024, I'm happy too ;) . Really i founded this solution after several hours test and try and wrote here for some one like you. – Ramin Bateni Sep 06 '16 at 21:55
2

Scroll body and check if it worked:

function getScrollableRoot() {
    var body = document.body;
    var prev = body.scrollTop;
    body.scrollTop++;
    if (body.scrollTop === prev) {
        return document.documentElement;
    } else {
        body.scrollTop--;
        return body;
    }
}


$(getScrollableRoot()).animate({ scrollTop: 0 }, "slow");

This is more efficient than $("html, body").animate because only one animation used, not two. Thus, only one callback fires, not two.

NVI
  • 14,907
  • 16
  • 65
  • 104
1
// if we are not already in top then see if browser needs html or body as selector
var obj = $('html').scrollTop() !== 0 ? 'html' : 'body';

// then proper delegate using on, with following line:
$(obj).animate({ scrollTop: 0 }, "slow");

BUT, best approach is to scroll an id into your viewport using just native api (since you scroll to top anyway this can be just your outer div):

document.getElementById('wrapperIDhere').scrollIntoView(true);
Beau Grantham
  • 3,435
  • 5
  • 33
  • 43
Maar10
  • 46
  • 2
  • This best approach bypasses the issue with `overflow-x: hidden;` on `html` in chrome. However it doesn't smooth scroll like `.animate()` does. – Jimmy Sep 05 '16 at 16:22
1

I use:

var $scrollEl = $.browser.mozilla ? $('html') : $('body');

because read jQuery scrollTop not working in Chrome but working in Firefox

Community
  • 1
  • 1
Aamir Afridi
  • 6,364
  • 3
  • 42
  • 42
1

maybe you mean top: 0

$('a#gotop').click(function() {
  $("html").animate({ top: 0 }, "slow", function() { 
                                           alert('Animation complete.'); });
  //return false;
});

from animate docs

.animate( properties, [ duration ], [ easing ], [ callback ] )
properties A map of CSS properties that the animation will move toward.
...

or $(window).scrollTop() ?

$('a#gotop').click(function() {
  $("html").animate({ top: $(window).scrollTop() }, "slow", function() { 
                                                              alert('Animation complete.'); });
  //return false;
});
Reigel Gallarde
  • 64,198
  • 21
  • 121
  • 139
  • still the animation is not working. Found simple solution.I had to use "body,html" or "html,body" instead of just "html". – Maju Jun 15 '10 at 06:20
0

A better way to solve this problem is to use a function like this:

function scrollToTop(callback, q) {

    if ($('html').scrollTop()) {
        $('html').animate({ scrollTop: 0 }, function() {
            console.log('html scroll');
            callback(q)
        });
        return;
    }

    if ($('body').scrollTop()) {
        $('body').animate({ scrollTop: 0 }, function() {
            console.log('body scroll');
            callback(q)
        });
        return;
    }

    callback(q);
}

This will work across all browsers and prevents FireFox from scrolling up twice (which is what happens if you use the accepted answer - $("html,body").animate({ scrollTop: 0 }, "slow");).

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
0

Testing on Chrome, Firefox and Edge, the only solution that worked fine for me is using setTimeout with the solution of Aaron in this way:

setTimeout( function () {
    $('body, html').stop().animate({ scrollTop: 0 }, 100);
}, 500);

No one of the other solutions resetted the previuos scrollTop, when I reloaded the page, in Chrome and Edge for me. Unfortunately there is still a little "flick" in Edge.

Ale
  • 117
  • 1
  • 13
0

So I was having this problem too and I have written this function:

/***Working function for ajax loading Start*****************/
function fuweco_loadMoreContent(elmId/*element ID without #*/,ajaxLink/*php file path*/,postParameterObject/*post parameters list as JS object with properties (new Object())*/,tillElementEnd/*point of scroll when must be started loading from AJAX*/){
 var 
  contener = $("#"+elmId),
  contenerJS = document.getElementById(elmId);
 if(contener.length !== 0){
  var 
   elmFullHeight = 
    contener.height()+
    parseInt(contener.css("padding-top").slice(0,-2))+
    parseInt(contener.css("padding-bottom").slice(0,-2)),
   SC_scrollTop = contenerJS.scrollTop,
   SC_max_scrollHeight = contenerJS.scrollHeight-elmFullHeight;
  if(SC_scrollTop >= SC_max_scrollHeight - tillElementEnd){
   $("#"+elmId).unbind("scroll");
   $.post(ajaxLink,postParameterObject)
    .done(function(data){
     if(data.length != 0){
     $("#"+elmId).append(data);
     $("#"+elmId).scroll(function (){
      fuweco_reloaderMore(elmId,ajaxLink,postParameterObject);
     });
    }
    });
  }
 }
}
/***Working function for ajax loading End*******************/
/***Sample function Start***********************************/
function reloaderMore(elementId) {
 var
  contener = $("#"+elementId),
  contenerJS = document.getElementById(elementId)
 ;

    if(contener.length !== 0){
     var
   elmFullHeight = contener.height()+(parseInt(contener.css("padding-top").slice(0,-2))+parseInt(contener.css("padding-bottom").slice(0,-2))),
   SC_scrollTop = contenerJS.scrollTop,
   SC_max_scrollHeight = contenerJS.scrollHeight-elmFullHeight
  ;
  if(SC_scrollTop >= SC_max_scrollHeight - 200){
   $("#"+elementId).unbind("scroll");
   $("#"+elementId).append('<div id="elm1" style="margin-bottom:15px;"><h1>Was loaded</h1><p>Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content. Some text for content.</p></div>');
   $("#"+elementId).delay(300).scroll(function (){reloaderMore(elementId);});
  }
    }
}
/***Sample function End*************************************/
/***Sample function Use Start*******************************/
$(document).ready(function(){
 $("#t1").scrollTop(0).scroll(function (){
  reloaderMore("t1");
    });
});
/***Sample function Use End*********************************/
.reloader {
    border: solid 1px red;
    overflow: auto;
    overflow-x: hidden;
    min-height: 400px;
    max-height: 400px;
    min-width: 400px;
    max-width: 400px;
    height: 400px;
    width: 400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
 <div class="reloader" id="t1">
  <div id="elm1" style="margin-bottom:15px;">
   <h1>Some text for header.</h1>
   <p>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
   </p>
  </div>
  <div id="elm2" style="margin-bottom:15px;">
   <h1>Some text for header.</h1>
   <p>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
   </p>
  </div>
  <div id="elm3" style="margin-bottom:15px;">
   <h1>Some text for header.</h1>
   <p>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
    Some text for content.<br>
   </p>
  </div>  
 </div>

I hope it will be helpfully for other programmers.

0

If it work all fine for Mozilla, with html,body selector, then there is a good chance that the problem is related to the overflow, if the overflow in html or body is set to auto, then this will cause chrome to not work well, cause when it is set to auto, scrollTop property on animate will not work, i don't know exactly why! but the solution is to omit the overflow, don't set it! that solved it for me! if you are setting it to auto, take it off!

if you are setting it to hidden, then do as it is described in "user2971963" answer (ctrl+f to find it). hope this is useful!

Mohamed Allal
  • 17,920
  • 5
  • 94
  • 97
0
 $("html, body").animate({ scrollTop: 0 }, "slow");

This CSS conflict with scroll to top so take care of this

 html, body {
         overflow-x: hidden;        
    }
Ashutosh Jha
  • 15,451
  • 11
  • 52
  • 85
0

I found that my CSS was the issue. I removed this from my style sheet and it worked fine.

*{scroll-behavior: smooth;}
-3

I don't think the scrollTop is a valid property. If you want to animate scrolling, try the scrollTo plugin for jquery

http://plugins.jquery.com/project/ScrollTo

Ben Rowe
  • 28,406
  • 6
  • 55
  • 75
  • When did I say scrollTop() is a property? You don't need to use a plugin as this function is already implemented in jQuery. – Bayard Randel Jun 15 '10 at 05:32
  • @Bayan - your deleted answer would have answer `When did I say scrollTop() is a property?` and besides, the OP want a smooth animation, can `scrollTop()` do smooth?... and it's worth noting that Ben's answer above clearly state, `I don't think the scrollTop is a valid property` and you commented as `scrollTop() is valid jQuery`... – Reigel Gallarde Jun 15 '10 at 05:46
  • 1
    @Maju fair enough. Glad to see you got your problem sorted however :) – Ben Rowe Jun 16 '10 at 01:19
  • @Reigel `ScrollTop` does smooth just fine: https://jsfiddle.net/JohnnyWalkerDesign/w4hetv45/ – Chuck Le Butt Mar 10 '16 at 12:30