212

Is there a way to control browser scrolling with JavaScript/jQuery?

When I scroll my page half way down, then trigger a reload, I want the page to go pack to the top, but instead it tries to find the last scroll position. So I did this:

$('document').ready(function() {
   $(window).scrollTop(0);
});

But no luck.

EDIT:

So both your answers worked when I call them after the page loads-Thanks. However, if I just do a refresh on the page, looks like the browser calculates and scrolls to its old scroll position AFTER the .ready event (I tested the body onload() function too).

So the follow up is, is there a way to PREVENT the browser scrolling to its past position, or to re-scroll to the top AFTER it does its thing?

3
  • 1
    What happens when you do it from $(window).load() ? Commented Nov 18, 2010 at 1:47
  • 2
    @MPD- Excellent idea! ... but just tried it and the scroll adjustment still happens after that. Thanks for the tip though, it actually helps with another question of mine: stackoverflow.com/questions/4210829/…. If you want to answer that one I'll give you some ups. Commented Nov 18, 2010 at 2:03
  • @Yarin Sorry you had to wait 9 years for this. You need set the history.scrollRestoration before you try to scroll. See my answer. Commented Nov 20, 2019 at 0:01

29 Answers 29

370

Cross-browser, pure JavaScript solution:

document.body.scrollTop = document.documentElement.scrollTop = 0;
Sign up to request clarification or add additional context in comments.

6 Comments

Since you're using jQuery, you could try this: $(window).one("scroll",function() { /* the code from my answer here */ });
To make this work on my IE/Chrome/FF cross-browsers, I must combine Niet Dark Absol answer and user113716 answer (using timeout).
Did not work on CentOS 6.7 using FF 45.1.0. I wrapped it in a document.ready just to be sure.
Just want to point out that from my testing (on modern/2018 versions of chrome included) that this solution works more reliably
This doesn't "PREVENT the browser scrolling to its past position". See my answer.
|
89
+50

You almost got it - you need to set the scrollTop on body, not window:

$(function() {
   $('body').scrollTop(0);
});

EDIT:

Maybe you can add a blank anchor to the top of the page:

$(function() {
   $('<a name="top"/>').insertBefore($('body').children().eq(0));
   window.location.hash = 'top';
});

2 Comments

Tried this today and didn't work in FF16. Using pure JS, seen lower on this page, instead: document.body.scrollTop = document.documentElement.scrollTop = 0;
The above code will work properly in Modern browsers like FF,Chrome but it will not work in IE8 and below try to add both 'html','body' as the modern browsers will scroll based on body but IE8 and below will only scroll with 'html','body'
77

Wow, I'm 9 years late to this question. Here you go:

Add this code to your onload.

// This prevents the page from scrolling down to where it was previously.
if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual';
}
// This is needed if the user scrolls down during page load and you want to make sure the page is scrolled to the top once it's fully loaded. This has Cross-browser support.
window.scrollTo(0,0);

To run it on window load just put it wrap it like this (assumes you have JQuery referenced)

$(function() {
  // put the code here
});

history.scrollRestoration Browser support:

Chrome: supported (since 46)

Firefox: supported (since 46)

Edge: supported (since 79)

IE: not supported

Opera: supported (since 33)

Safari: supported

For IE if you want to re-scroll to the top AFTER it autoscrolls down then this worked for me:

var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
if(isIE11) {
    setTimeout(function(){ window.scrollTo(0, 0); }, 300);  // adjust time according to your page. The better solution would be to possibly tie into some event and trigger once the autoscrolling goes to the top.
} 

5 Comments

Thanks @RayLoveless - unfortunately this isn't supported by MS browsers (because of course). See caniuse.com/#feat=mdn-api_history_scrollrestoration and developer.mozilla.org/de/docs/Web/API/…
@Yarin, Good point. I updated my post. Does that answer your question?
@RayLoveless It's supported on Edge now.
@NikolaStojaković, Thanks, I've updated accordingly.
Upvoting because it's never too late to help someone; even if it's 9 years later. Thank you!
31

UPDATE

Going to top of the page with a scroll effect is a bit more easier in javascript now with:

https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll

There are 2 ways to use scroll API.

This is the method I recommend. Using an option object:

window.scroll(options)

This is a better option since you can define a behavior prop which applies a built-in easing animation.

window.scroll({
 top: 0, 
 left: 0, 
 behavior: 'smooth' 
});

The other method is to use an x and y coordinates.

window.scroll(x-coord, y-coord)

x-coord - is the pixel along the horizontal axis of the document that you want displayed in the upper left.

y-coord - is the pixel along the vertical axis of the document that you want displayed in the upper left.


OLD ANSWER DO NOT USE

This is our vanilla javascript implementation. It has a simple easing effect so that the user doesn't get shocked after clicking the To Top button.

Its very small and gets even smaller when minified. Devs looking for an alternative to the jquery method but want the same results can try this.

JS

document.querySelector("#to-top").addEventListener("click", function(){

    var toTopInterval = setInterval(function(){

        var supportedScrollTop = document.body.scrollTop > 0 ? document.body : document.documentElement;

        if (supportedScrollTop.scrollTop > 0) {
            supportedScrollTop.scrollTop = supportedScrollTop.scrollTop - 50;
        }

        if (supportedScrollTop.scrollTop < 1) {
            clearInterval(toTopInterval);
        }

    }, 10);

},false);

HTML

<button id="to-top">To Top</button>

Cheers!

Comments

19

Is there a way to PREVENT the browser scrolling to its past position, or to re-scroll to the top AFTER it does its thing?

The following jquery solution works for me:

$(window).unload(function() {
    $('body').scrollTop(0);
});

2 Comments

yea scroll to top before the refresh
Not completely cross browser, but still works for most. When coupled with some of the other answers this is a good addition
18

Here's a pure JavaScript animated scroll version for no-jQuery'ers :D

var stepTime = 20;
var docBody = document.body;
var focElem = document.documentElement;

var scrollAnimationStep = function (initPos, stepAmount) {
    var newPos = initPos - stepAmount > 0 ? initPos - stepAmount : 0;

    docBody.scrollTop = focElem.scrollTop = newPos;

    newPos && setTimeout(function () {
        scrollAnimationStep(newPos, stepAmount);
    }, stepTime);
}

var scrollTopAnimated = function (speed) {
    var topOffset = docBody.scrollTop || focElem.scrollTop;
    var stepAmount = topOffset;

    speed && (stepAmount = (topOffset * stepTime)/speed);

    scrollAnimationStep(topOffset, stepAmount);
};

And then:

<button onclick="scrollTopAnimated(1000)">Scroll Top</button>

2 Comments

Cool. Though, I would prefer requestAnimationStep instead of setTimeout. Also it does not answer OP's question.
implemented this in Angular. works like a charm. Thanks
17

A modern solution in 2021

document.body.scrollIntoView({behavior: "smooth"});

Works with every browser including IE (older browsers don't support smooth scrolling).

enter image description here

Comments

12

This works for me:

window.onload = function() {
    // short timeout
    setTimeout(function() {
        $(document.body).scrollTop(0);
    }, 15);
};

Uses a short setTimeout inside the onload to give the browser a chance to do the scroll.

2 Comments

To make this work on my IE/Chrome/FF cross-browsers, I must combine Niet Dark Absol answer and user113716 answer (using timeout).
@Panini: your suggestion works for me on Chrome/FF, but not IE11.
10

You can use with jQuery

jQuery(window).load(function(){

    jQuery("html,body").animate({scrollTop: 100}, 1000);

});

1 Comment

This is basically what I FINALLY found to work on CentOS 6.7 using FF 45.1.0. My slightly different version (wrapped in a window load function) is: $("html, body").animate({ scrollTop: 0 }, 1);
10

Use the following function

window.scrollTo(xpos, ypos)

Here xpos is Required. The coordinate to scroll to, along the x-axis (horizontal), in pixels

ypos is also Required. The coordinate to scroll to, along the y-axis (vertical), in pixels

Comments

6

The following code works in Firefox, Chrome and Safari, but I was unable to test this in Internet Explorer. Can someone test it, and then edit my answer or comment on it?

$(document).scrollTop(0);

Comments

5

Use this:

$(function() {
    // the element inside of which we want to scroll
        var $elem = $('#content');

        // show the buttons
    $('#nav_up').fadeIn('slow');
    $('#nav_down').fadeIn('slow');  

        // whenever we scroll fade out both buttons
    $(window).bind('scrollstart', function(){
        $('#nav_up,#nav_down').stop().animate({'opacity':'0.2'});
    });
        // ... and whenever we stop scrolling fade in both buttons
    $(window).bind('scrollstop', function(){
        $('#nav_up,#nav_down').stop().animate({'opacity':'1'});
    });

        // clicking the "down" button will make the page scroll to the $elem's height
    $('#nav_down').click(
        function (e) {
            $('html, body').animate({scrollTop: $elem.height()}, 800);
        }
    );
        // clicking the "up" button will make the page scroll to the top of the page
    $('#nav_up').click(
        function (e) {
            $('html, body').animate({scrollTop: '0px'}, 800);
        }
    );
 });

1 Comment

Nice! Works fine with animation!
4

Why don't you just use some reference element at the very beginning of your html file, like

<div id="top"></div>

and then, when the page loads, simply do

$(document).ready(function(){

    top.location.href = '#top';

});

If the browser scrolls after this function fires, you simply do

$(window).load(function(){

    top.location.href = '#top';

});

1 Comment

this worked for me, but it adds the #top in the url, can you please tell me how can i avoid this, but at the same time, not compromising with the functionality
4

Cross-browser scroll to top:

        if($('body').scrollTop()>0){
            $('body').scrollTop(0);         //Chrome,Safari
        }else{
            if($('html').scrollTop()>0){    //IE, FF
                $('html').scrollTop(0);
            }
        } 

Cross-browser scroll to an element with id = div_id:

        if($('body').scrollTop()>$('#div_id').offset().top){
            $('body').scrollTop($('#div_id').offset().top);         //Chrome,Safari
        }else{
            if($('html').scrollTop()>$('#div_id').offset().top){    //IE, FF
                $('html').scrollTop($('#div_id').offset().top);
            }
        } 

Comments

4

My pure (animated) Javascript solution:

function gototop() {
    if (window.scrollY>0) {
        window.scrollTo(0,window.scrollY-20)
        setTimeout("gototop()",10)
    }
}

Explanation:

window.scrollY is a variable maintained by the browser of the amount of pixels from the top that the window has been scrolled by.

window.scrollTo(x,y) is a function that scrolls the window a specific amount of pixels on the x axis and on the y axis.

Thus, window.scrollTo(0,window.scrollY-20) moves the page 20 pixels towards the top.

The setTimeout calls the function again in 10 milliseconds so that we can then move it another 20 pixels (animated), and the if statement checks if we still need to scroll.

Comments

3

If you're in quircks mode (thanks @Niet the Dark Absol):

document.body.scrollTop = document.documentElement.scrollTop = 0;

If you're in strict mode:

document.documentElement.scrollTop = 0;

No need for jQuery here.

Comments

3

In my case body didn't worked:

$('body').scrollTop(0);

But HTML worked:

$('html').scrollTop(0);

1 Comment

Add both 'html','body' as the modern browsers FF,Chrome will scroll based on body but IE8 and below will only scroll with 'html','body'
2

To answer your edited-in question, you could register the onscroll handler like so:

document.documentElement.onscroll = document.body.onscroll = function() {
    this.scrollTop = 0;
    this.onscroll = null;
}

This will make it so that the first attempt at scrolling (which is likely the automatic one done by the browser) will be effectively cancelled.

Comments

2

without animation, just scroll(0, 0) (vanilla JS)

Comments

2

Combination of these two helped me. None of the other answers helped me since i had a sidenav that was not scrolling.

 setTimeout(function () {
        window.scroll({
                        top: 0,
                        left: 0,
                        behavior: 'smooth'
                    });

    document.body.scrollTop = document.documentElement.scrollTop = 0;

}, 15);

Comments

2

I remember seeing this posted somewhere else (I couldn't find where), but this works really well:

setTimeout(() => {
    window.scrollTo(0, 0);
}, 0);

It's weird, but the way it works is based off of the way JavaScript's stack queue works. The full explanation is found here in the Zero Delays section.

The basic idea is that the time for setTimeout doesn't actually specify the set amount of time it will wait, but the minimum amount of time it will wait. So when you tell it to wait 0ms, the browser runs all the other queued processes (like scrolling the window to where you were last) and then executes the callback.

Comments

1
var totop = $('#totop');
totop.click(function(){
 $('html, body').stop(true,true).animate({scrollTop:0}, 1000);
 return false;
});

$(window).scroll(function(){
 if ($(this).scrollTop() > 100){ 
  totop.fadeIn();
 }else{
  totop.fadeOut();
 }
});

<img id="totop" src="img/arrow_up.png" title="Click to go Up" style="display:none;position:fixed;bottom:10px;right:10px;cursor:pointer;cursor:hand;"/>

Comments

1

This is working:

jQuery(document).ready(function() {
     jQuery("html").animate({ scrollTop: 0 }, "fast");
});

Comments

1

If anyone is using angular and material design with sidenav. This will send you to to the top of the page:

let ele = document.getElementsByClassName('md-sidenav-content');
    let eleArray = <Element[]>Array.prototype.slice.call(ele);
    eleArray.map( val => {
        val.scrollTop = document.documentElement.scrollTop = 0;
    });

Comments

0

Seeint the hash should do the job. If you have a header, you can use

window.location.href = "#headerid";

otherwise, the # alone will work

window.location.href = "#";

And as it get written into the url, it'll stay if you refresh.

In fact, you don't event need JavaScript for that if you want to do it on an onclick event, you should just put a link arround you element and give it # as href.

1 Comment

Btw, window.location isn't part of the tree so there is now use to wait for onload.
0

First add a blank anchor tag to the place where you want to go

<a href="#topAnchor"></a> 

Now add a function in header section

 function GoToTop() {
            var urllocation = location.href;
            if (urllocation.indexOf("#topAnchor") > -1) {
                window.location.hash = "topAnchor";
            } else {
                return false;
            }
        }

finally add an onload event to the body tag

<body onload="GoToTop()">

Comments

0

A generic version that works for any X and Y value, and is the same as the window.scrollTo api, just with the addition of scrollDuration.

*A generic version matching the window.scrollTo browser api**

function smoothScrollTo(x, y, scrollDuration) {
    x = Math.abs(x || 0);
    y = Math.abs(y || 0);
    scrollDuration = scrollDuration || 1500;

    var currentScrollY = window.scrollY,
        currentScrollX = window.scrollX,
        dirY = y > currentScrollY ? 1 : -1,
        dirX = x > currentScrollX ? 1 : -1,
        tick = 16.6667, // 1000 / 60
        scrollStep = Math.PI / ( scrollDuration / tick ),
        cosParameterY = currentScrollY / 2,
        cosParameterX = currentScrollX / 2,
        scrollCount = 0,
        scrollMargin;

    function step() {        
        scrollCount = scrollCount + 1;  

        if ( window.scrollX !== x ) {
            scrollMargin = cosParameterX + dirX * cosParameterX * Math.cos( scrollCount * scrollStep );
            window.scrollTo( 0, ( currentScrollX - scrollMargin ) );
        } 

        if ( window.scrollY !== y ) {
            scrollMargin = cosParameterY + dirY * cosParameterY * Math.cos( scrollCount * scrollStep );
            window.scrollTo( 0, ( currentScrollY - scrollMargin ) );
        } 

        if (window.scrollX !== x || window.scrollY !== y) {
            requestAnimationFrame(step);
        }
    }

    step();
}

Comments

0
document.querySelector(".elementName").scrollIntoView()

Note: select the element which contains scroll.

Comments

-1
 <script>
  sessionStorage.scrollDirection = 1;//create a session variable 
  var pageScroll = function() {
  window.scrollBy ({
   top: sessionStorage.scrollDirection,
   left: 0,
   behavior: 'smooth'
   });
   if($(window).scrollTop() + $(window).height() > $(document).height() - 1)
  {    
    sessionStorage.scrollDirection= Number(sessionStorage.scrollDirection )-300;
    setTimeout(pageScroll,50);//
   }
   else{
   sessionStorage.scrollDirection=Number(sessionStorage.scrollDirection )+1
   setTimeout(pageScroll,300); 
  }
};
pageScroll();
</script>

1 Comment

Welcome to stackoverflow. In addition to the code you've provided, try to give some explanation on why and how this fixes the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.