'Can I update window.location.hash without having the web page scroll?

Using JavaScript, is there a way to update window.location.hash without scrolling the web page?

I have clickable title elements that toggle the visibility of a div directly beneath them. I want the /foo#bar in the history when clicking titles but don't want the page scrolling about. So when navigating away from /foo#bar I'll be able to use the back button and have the div whose ID is in window.location.hash be visible upon return.

Is this behavior possible?



Solution 1:[1]

To change the hash without having the page reload/scroll, you can now simply use html5 history.pushState.

history.pushState(null,null,'#hashexample');

It's supported by all the major browsers:

http://caniuse.com/history

MDN:

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#The_pushState().C2.A0method

Also note that the last url parameter we're using here, it can be any url, so it's not limited to hashes.

Solution 2:[2]

As easy as it get

var scrollmem = $('html,body').scrollTop();
window.location.hash = hash;
$('html,body').scrollTop(scrollmem);

Solution 3:[3]

Another thing you could try is changing the id of the element the hash points to temporarily. Worked for me!

function changeHashWithoutScrolling(hash) {
  const id = hash.replace(/^.*#/, "")
  const elem = document.getElementById(id)
  if (elem) {
    elem.id = id + "-tmp"
    window.location.hash = hash
    elem.id = id
  }
}

Solution 4:[4]

Based on the answer from Sunny I made this function that also avoids undefined and nulls:

    function changeHashWithoutScrolling(hash) {
        var id;
        var elem;

        id = hash.replace(/^.*#/, '');

        if (id) {
            elem = document.getElementById(id);

            if (elem) {
                elem.id = id + '-tmp';
                window.location.hash = hash;
                elem.id = id;
            }
        }
    }

Solution 5:[5]

Wanted to add a comment to Catherines answer but I don't have the rep yet -

Great solution however it wasn't working for me in Chrome as $('html').scrollTop() always returns 0 - a minor edit resolves the issue:

scrollmem = $('html').scrollTop() || $('body').scrollTop();
window.location.hash = hash;
$('html,body').scrollTop(scrollmem);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mosh Feu
Solution 2 Jeff Davis
Solution 3
Solution 4
Solution 5 Brian