How can I remove the location hash without causing the page to scroll?

JavascriptJqueryFragment Identifier

Javascript Problem Overview


Is it possible to remove the hash from window.location without causing the page to jump-scroll to the top? I need to be able to modify the hash without causing any jumps.

I have this:

$('<a href="#123">').text('link').click(function(e) {
  e.preventDefault();
  window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
  e.preventDefault();
  window.location.hash = '';
}).appendTo('body');

See live example here: http://jsbin.com/asobi

When the user clicks 'link' the hash tag is modified without any page jumps, so that's working fine.

But when the user clicks 'unlink' the has tag is removed and the page scroll-jumps to the top. I need to remove the hash without this side-effect.

Javascript Solutions


Solution 1 - Javascript

I believe if you just put in a dummy hash it won't scroll as there is no match to scroll to.

<a href="#A4J2S9F7">No jumping</a>

or

<a href="#_">No jumping</a>

"#" by itself is equivalent to "_top" thus causes a scroll to the top of the page

Solution 2 - Javascript

I use the following on a few sites, NO PAGE JUMPS!

Nice clean address bar for HTML5 friendly browsers, and just a # for older browsers.

$('#logo a').click(function(e){
	window.location.hash = ''; // for older browsers, leaves a # behind
	history.pushState('', document.title, window.location.pathname); // nice and clean
	e.preventDefault(); // no page reload
});

Solution 3 - Javascript

window.location's hash property is stupid in a couple of ways. This is one of them; the other is that is has different get and set values:

window.location.hash = "hello";  // url now reads *.com#hello
alert(window.location.hash);   // shows "#hello", which is NOT what I set.
window.location.hash = window.location.hash; // url now reads *.com##hello

Note that setting the hash property to '' removes the hash mark too; that's what redirects the page. To set the value of the hash part of the url to '', leaving the hash mark and therefore not refreshing, write this:

window.location.href = window.location.href.replace(/#.*$/, '#');

There is no way to completely remove the hash mark once set without refreshing the page.

UPDATE 2012:

As Blazemonger and thinkdj have pointed out, technology has improved. Some browsers do allow you to clear that hashtag, but some do not. To support both, try something like:

if ( window.history && window.history.pushState ) { 
    window.history.pushState('', '', window.location.pathname) 
} else { 
    window.location.href = window.location.href.replace(/#.*$/, '#'); 
}

Solution 4 - Javascript

This is an old post but I wanted to share my solution All the links in my project that being handled by JS are having href="#_js" attribute (or whatever name you want to use for that purposes only), and on page initialization I do:

$('body').on('click.a[href="#_js"]', function() {
    return false;
});

That'll do the trick

Solution 5 - Javascript

Setting window.location.hash to empty or non-existing anchor name, will always force the page to jump to top. The only way to prevent this is to grab the scroll position of the window and set it to that position again after the hash change.

This will also force a repaint of the page (cant avoid it), though since it's executed in a single js process, it won't jump up/down (theoretically).

$('<a href="#123">').text('link').click(function(e) {
	e.preventDefault();
	window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
	e.preventDefault();
    var pos = $(window).scrollTop(); // get scroll position
	window.location.hash = '';
    $(window).scrollTop(pos); // set scroll position back
}).appendTo('body');

Hope this helps.

Solution 6 - Javascript

I'm not sure if this produces the desired outcome, give it a shot:

$('<a href="#">').text('unlink').click(function(e) {
    e.preventDefault();
    var st = parseInt($(window).scrollTop())
    window.location.hash = '';
    $('html,body').css( { scrollTop: st });  
});
   

Basically save the scroll offset and restore it after assigning the empty hash.

Solution 7 - Javascript

Have you tried return false; in the event handler? jQuery does something special when you do that, similar to, but AFAIK more impactful, than e.preventDefault.

Solution 8 - Javascript

Hope this helps

html

<div class="tabs">
  <ul>
    <li><a href="#content1">Tab 1</a></li>
    <li><a href="#content2">Tab 2</a></li>
    <li><a href="#content3">Tab 3</a></li>
  </ul>
</div>
<div class="content content1">
	<p>1. Content goes here</p>
</div>
<div class="content content2">
	<p>2. Content goes here</p>
</div>
<div class="content content3">
	<p>3. Content goes here</p>
</div>

js

function tabs(){
  $(".content").hide();

  if (location.hash !== "") {
    $('.tabs ul li:has(a[href="' + location.hash + '"])').addClass("active");
    var hash = window.location.hash.substr(1);
    var contentClass = "." + hash;
    $(contentClass).fadeIn();
  } else {
    $(".tabs ul li").first().addClass("active");
    $('.tabs').next().css("display", "block");
  }
}
tabs();

$(".tabs ul li").click(function(e) {
  $(".tabs ul li").removeAttr("class");
  $(this).addClass("active");
  $(".content").hide();
  var contentClass = "." + $(this).find("a").attr("href").substr(1);
  $(contentClass).fadeIn();
  window.location.hash = $(this).find("a").attr("href");
  e.preventDefault();
  return false;
});

URL without any hash.
<http://output.jsbin.com/tojeja>

URL with hashtag that does not jumping to anchor.
<http://output.jsbin.com/tojeja#content1>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid HellsingView Question on Stackoverflow
Solution 1 - JavascriptscunliffeView Answer on Stackoverflow
Solution 2 - JavascriptneokioView Answer on Stackoverflow
Solution 3 - JavascriptolooneyView Answer on Stackoverflow
Solution 4 - JavascriptTomer GalView Answer on Stackoverflow
Solution 5 - JavascriptBGerrissenView Answer on Stackoverflow
Solution 6 - JavascriptTom BartelView Answer on Stackoverflow
Solution 7 - JavascriptRoman NurikView Answer on Stackoverflow
Solution 8 - JavascriptShak DanielView Answer on Stackoverflow