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.