When I have a link that is wired-up with a jQuery or JavaScript event such as:
<a href="#">My Link</a>
How do I prevent the page from scrolling to the top? When I remove the href attribute from the anchor the page doesn't scroll to the top but the link doesn't appear to be click-able.
You need to prevent the default action for the click event (i.e. navigating to the link target) from occurring.
There are two ways to do this.
Option 1: event.preventDefault()
Call the .preventDefault()
method of the event object passed to your handler. If you're using jQuery to bind your handlers, that event will be an instance of jQuery.Event
and it will be the jQuery version of .preventDefault()
. If you're using addEventListener
to bind your handlers, it will be an Event
and the raw DOM version of .preventDefault()
. Either way will do what you need.
Examples:
$('#ma_link').click(function($e) {
$e.preventDefault();
doSomething();
});
document.getElementById('#ma_link').addEventListener('click', function (e) {
e.preventDefault();
doSomething();
})
Option 2: return false;
Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault()
So, with jQuery, you can alternatively use this approach to prevent the default link behaviour:
$('#ma_link').click(function(e) {
doSomething();
return false;
});
If you're using raw DOM events, this will also work on modern browsers, since the HTML 5 spec dictates this behaviour. However, older versions of the spec did not, so if you need maximum compatibility with older browsers, you should call .preventDefault()
explicitly. See event.preventDefault() vs. return false (no jQuery) for the spec detail.
You can set your href to #!
instead of #
For example,
<a href="#!">Link</a>
will not do any scrolling when clicked.
Beware! This will still add an entry to the browser's history when clicked, meaning that after clicking your link, the user's back button will not take them to the page they were previously on. For this reason, it's probably better to use the .preventDefault()
approach, or to use both in combination.
Here is a Fiddle illustrating this (just scrunch your browser down until your get a scrollbar):
http://jsfiddle.net/9dEG7/
For the spec nerds - why this works:
This behaviour is specified in the HTML5 spec under the Navigating to a fragment identifier section. The reason that a link with a href of "#"
causes the document to scroll to the top is that this behaviour is explicitly specified as the way to handle an empty fragment identifier:
2. If fragid is the empty string, then the indicated part of the document is the top of the document
Using a href of "#!"
instead works simply because it avoids this rule. There's nothing magic about the exclamation mark - it just makes a convenient fragment identifier because it's noticeably different to a typical fragid and unlikely to ever match the id
or name
of an element on your page. Indeed, we could put almost anything after the hash; the only fragids that won't suffice are the empty string, the word 'top', or strings that match name
or id
attributes of elements on the page.
More exactly, we just need a fragment identifier that will cause us to fall through to step 8 in the following algorithm for determining the indicated part of the document from the fragid:
Apply the URL parser algorithm to the URL, and let fragid be the fragment component of the resulting parsed URL. If fragid is the empty string, then the indicated part of the document is the top of the document; stop the algorithm here. Let fragid bytes be the result of percent-decoding fragid. Let decoded fragid be the result of applying the UTF-8 decoder algorithm to fragid bytes. If the UTF-8 decoder emits a decoder error, abort the decoder and instead jump to the step labeled no decoded fragid. If there is an element in the DOM that has an ID exactly equal to decoded fragid, then the first such element in tree order is the indicated part of the document; stop the algorithm here. No decoded fragid: If there is an a element in the DOM that has a name attribute whose value is exactly equal to fragid (not decoded fragid), then the first such element in tree order is the indicated part of the document; stop the algorithm here. If fragid is an ASCII case-insensitive match for the string top, then the indicated part of the document is the top of the document; stop the algorithm here. Otherwise, there is no indicated part of the document.
As long as we hit step 8 and there is no indicated part of the document, the following rule comes into play:
If there is no indicated part ... then the user agent must do nothing.
which is why the browser doesn't scroll.
preventDefault()
in a click handler - rather sadly.
An easy approach is to leverage this code:
<a href="javascript:void(0);">Link Title</a>
This approach doesn't force a page refresh, so the scrollbar stays in place. Also, it allows you to programmatically change the onclick event and handle client side event binding using jQuery.
For these reasons, the above solution is better than:
<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>
where the last solution will avoid the scroll-jump issue if and only if the myClickHandler method doesn't fail.
You should change the
<a href="#">My Link</a>
to
<a href="javascript:;">My Link</a>
This way when the link is clicked the page won't scroll to top. This is cleaner than using href="#" and then preventing the default event from running.
I have good reasons for this on the first answer to this question, like the return false;
will not execute if the called function throws an error, or you may add the return false;
to a doSomething()
function and then forget to use return doSomething();
Returning false from the code you're calling will work and in a number of circumstances is the preferred method but you can also so this
<a href="javascript:;">Link Title</a>
When it comes to SEO it really depends on what your link is going to be used for. If you are going to actually use it to link to some other content then I would agree ideally you would want something meaningful here but if you are using the link for functionality purposes maybe like Stack Overflow does for the post toolbar (bold, italic, hyperlink, etc) then it probably doesn't matter.
Try this:
<a href="#" onclick="return false;">My Link</a>
If you can simply change the href
value, you should use:
<a href="javascript:void(0);">Link Title</a>
Another neat solution I just came up with is to use jQuery to stop the click action from occurring and causing the page to scroll, but only for href="#"
links.
<script type="text/javascript">
/* Stop page jumping when links are pressed */
$('a[href="#"]').live("click", function(e) {
return false; // prevent default click action from happening!
e.preventDefault(); // same thing as above
});
</script>
return false
should be after the preventDefault()
line, otherwise you'll never get to this second line?
Link to something more sensible than the top of the page in the first place. Then cancel the default event.
See rule 2 of pragmatic progressive enhancement.
Also, you can use event.preventDefault inside onclick attribute.
<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>
No need to write exstra click event.
For Bootstrap 3 for collapse, if you don't specify data-target on the anchor and rely on href to determine the target, the event will be prevented. If you use data-target you'll need to prevent the event yourself.
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>
<div id="demo" class="collapse">
<p>Lorem ipsum dolor sit amet</p>
</div>
You can simply write like this also:-
<a href="#!" onclick="function()">Delete User</a>
When calling the function, follow it by return false
example:
<input type="submit" value="Add" onclick="addNewPayment();return false;">
Create a page which contains two links- one at the top and one at the bottom. On clicking the top link, the page has to scroll down to the bottom of the page where bottom link is present. On clicking the bottom link, the page has to scroll up to the top of the page.
<a onclick="yourfunction()">
this will work fine . no need to add href="#"
You might want to check your CSS. In the example here: https://css-tricks.com/the-checkbox-hack/ there's position: absolute; top: -9999px;
. This is particularly goofy on Chrome, as onclick="whatever"
still jumps to the absolute position of the clicked element.
Removing position: absolute; top: -9999px;
, for display: none;
might help.
event.preventDefault()
will stop the scrolling but also not change the link state to visited (color)
, which I need. The "3 years late" solution is not too late and eliminates unforseen side-effects. The hrefs I create are in a loop (indexed by "i") "#i!", where i is the index to an array containing the text for the anchor tag. Works like a charm. (Just #i would work too, except I have other ids set to i).
While I'd like to use the `href='javascript:function()'` approach, this adds 11 bytes (javascript:) plus the bytes of the function name plus parameters to the page size. Mutiply this by 1000+ hrefs and thats 16kb+ added to the page size. (Yes, pagination would help but not for the user). So maybe in a different situation I'd go with the javascript: solution.
Success story sharing