anchor jumping by using javascript
Asked Answered
E

7

154

I have a question that will be found very often. The problem is that nowhere can be found an explicit solution.

I have two problems regarding anchors.

The main goal should be to get a nice clean url without any hashes in it while using anchors to jump on a page.

So the structure of the anchors is:

<ul>
    <li><a href="#one">One</a></li>
    <li><a href="#two">Two</a></li>
    <li><a href="#three">Three</a></li>
</ul>

<div class="wrap">
    <a name="one">text 1</a>
    <a name="two">text 2</a>
    <a name="three" class="box">text 3</a>
</div>

Okay, if you will click one of the links the url will automatically change to

www.domain.com/page#1

At the end this should be just:

www.domain.com/page

So far, so good. Now the second thing is, when you search the internet for that problem you will find javascript as a solution.

I have found this function:

function jumpto(anchor){
    window.location.href = "#"+anchor;
}

and calling that function with:

<a onclick="jumpto('one');">One</a>

what will be the same like before. It will add the hash to the url. I also added

<a onclick="jumpto('one'); return false;">

without success. So if there is someone who could tell me how to solve this I really would appreciate.

Thanks a lot.

Enamour answered 6/12, 2012 at 2:15 Comment(6)
Not sure about this, but you could try manually writing to the hash property after the jump. For example set a timeout in the onclick handler which sets window.location.hash=''.Leary
Do you mean you don't want to have the # shown in the URL when jumping to another section in the same webpage?Tarratarradiddle
In that case you will either have to manipulate the scrollTop of the window, typically by window.scrollTo or the corresponding jQuery helper: https://mcmap.net/q/40468/-scroll-to-an-element-with-jquery or #500836Accusatorial
@Leary - If you do location.hash='', the # remains there.Resistant
Do not do that, please. Hashes are good when saving the page in your bookmarks.Tijuana
Perhaps worth noting that the name attribute of anchor tags is deprecated. You should use id instead.Kaceykachina
H
253

You can get the coordinate of the target element and set the scroll position to it. But this is so complicated.

Here is a lazier way to do that:

function jump(h){
    var url = location.href;               //Save down the URL without hash.
    location.href = "#"+h;                 //Go to the target element.
    history.replaceState(null,null,url);   //Don't like hashes. Changing it back.
}

This uses replaceState to manipulate the url. If you also want support for IE, then you will have to do it the complicated way:

function jump(h){
    var top = document.getElementById(h).offsetTop; //Getting Y of target element
    window.scrollTo(0, top);                        //Go there directly or some transition
}​

Demo: http://jsfiddle.net/DerekL/rEpPA/
Another one w/ transition: http://jsfiddle.net/DerekL/x3edvp4t/

You can also use .scrollIntoView:

document.getElementById(h).scrollIntoView();   //Even IE6 supports this

(Well I lied. It's not complicated at all.)

Hispania answered 6/12, 2012 at 2:53 Comment(16)
Rats!! The link is broken :-( I thought that JS Fiddles stayed there foreverEdette
@Edette Apparently they have removed the ability to use add /show at the end of the url.Resistant
"Even IE6 supports this" is the best comment I've ever seen.Cumulative
@Derek朕會功夫 do you have a case of Mondays? (profile picture from Office Space movie)Braces
@JuanMendez Yes :)Resistant
I think the "complicated" way is even easier than the simple way. I prefer the scrolling than tagGerardogeratology
.scrollIntoView does not seem to work with a Jquery Element.Honeycutt
@Honeycutt There are no such thing as a “jQuery” element. If you want to get the first element out from your query, do $(mySelector)[0].scrollIntoView().Resistant
@Honeycutt I’m not sure what you mean by “hidden elements” either. All elements in your DOM subclass from HTMLElement which definitely contains the .scrollIntoView method.Resistant
@Derek朕會功夫, I mean elements which have the attribute hidden. e.g. <p id='goToTop' hidden></p>Honeycutt
@Honeycutt You might want to redesign your page if you need to jump to a hidden element.Resistant
@Derek朕會功夫, what are the reasons why this is bad?Honeycutt
Let us continue this discussion in chat.Resistant
1+ for scrollIntoView. 1- for mentioning it last.Eastwood
I find the "window.scrollTo(0, element.offsetTop)" method the best as it works perfectly with windows not on full screen (unlike scrollIntoView()). Also, this function alignes the element to the very top of the screen, making it easier to spot the change.Goble
I couldn't make this to work. For some reason in my system / case document.getElementById(h).offsetTop return wrong values all the time. So I went the Jquery way: window.scrollTo(0, $("#elem").offset());Cauldron
A
22

I think it is much more simple solution:

window.location = (""+window.location).replace(/#[A-Za-z0-9_]*$/,'')+"#myAnchor"

This method does not reload the website, and sets the focus on the anchors which are needed for screen reader.

Asthenic answered 13/1, 2016 at 12:6 Comment(5)
And what rarely works on IE ,this works on all IE ;)Asthenic
I ended up with window.location = window.location.origin + window.location.pathname + '#hash';Melessa
This reloaded the page for me. Accepted answer ended up working, though, I wish it was shorter.Mahlstick
This is the Best way !!Indiscriminate
@Melessa Isn't that missing the protocol?Loco
M
7

I don't have enough rep for a comment.

The getElementById() based method in the selected answer won't work if the anchor has name but not id set (which is not recommended, but does happen in the wild).

Something to bear in mind if you don't have control of the document markup (e.g. webextension).

The location based method in the selected answer can also be simplified with location.replace:

function jump(hash) { location.replace("#" + hash) }
Midshipmite answered 10/6, 2018 at 15:13 Comment(0)
V
3

Because when you do

window.location.href = "#"+anchor;

You load a new page, you can do:

<a href="#" onclick="jumpTo('one');">One</a>
<a href="#" id="one"></a>

<script>

    function getPosition(element){
        var e = document.getElementById(element);
        var left = 0;
        var top = 0;

        do{
            left += e.offsetLeft;
            top += e.offsetTop;
        }while(e = e.offsetParent);

        return [left, top];
    }

    function jumpTo(id){    
        window.scrollTo(getPosition(id));
    }

</script>
Virile answered 6/12, 2012 at 2:42 Comment(4)
I don't think adding hashes makes it a new page.Resistant
It doesn't reload the page.Resistant
You're right it doesn't reload page. I try in console with chrome and the favicon is reloaded.Virile
In the latest Firefox, hash changes seem to force a reload for iFrames (in the src attribute). I'd consider this a browser bug, but something to be aware of.Moise
R
2

I have a button for a prompt that on click it opens the display dialogue and then I can write what I want to search and it goes to that location on the page. It uses javascript to answer the header.

On the .html file I have:

<button onclick="myFunction()">Load Prompt</button>
<span id="test100"><h4>Hello</h4></span>

On the .js file I have

function myFunction() {
    var input = prompt("list or new or quit");

    while(input !== "quit") {
        if(input ==="test100") {
            window.location.hash = 'test100';
            return;
// else if(input.indexOf("test100") >= 0) {
//   window.location.hash = 'test100';
//   return;
// }
        }
    }
}

When I write test100 into the prompt, then it will go to where I have placed span id="test100" in the html file.

I use Google Chrome.

Note: This idea comes from linking on the same page using

<a href="#test100">Test link</a>

which on click will send to the anchor. For it to work multiple times, from experience need to reload the page.

Credit to the people at stackoverflow (and possibly stackexchange, too) can't remember how I gathered all the bits and pieces. ☺

Raimund answered 24/6, 2017 at 2:34 Comment(0)
L
1

This is the simplest solution I've found to this that is also pretty robust:

window.location.href = window.location.href.split("#")[0] + "#your-anchor";

This:

  • Doesn't strip the anchor from the URL unlike scrollToView (better for shareability/UX and useful for analytics)
  • Works no matter how many hashes are currently in the URL - whether 0, 1 or 20 - so won't fail if clicked more than once
  • Doesn't reload the page
Loco answered 18/9, 2023 at 17:51 Comment(0)
P
0

The first suggested solution of accepted solution did not work for me entirely. The main problem was when it was already jumped to hash, and hash already in url, jump did not happen again. I propose here, for the sake of completeness, somewhat more elaborate solution which works (tested in Chrome and FF). el is element with anchor tag.

        el.addEventListener('click', function(ev) {
            ev.preventDefault();
            const href = ev.target.getAttribute('href');
            const hashIndex = href.indexOf('#');
            if (hashIndex !== -1) {
                const hashPart = href.substring(hashIndex);
                if (location.hash === hashPart) {
                    document.querySelector(hashPart).scrollIntoView();
                }
                else {
                    location.hash = hashPart;
                }
            }
        })
Puppy answered 7/6, 2022 at 17:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.