Changing active states of anchor links as the user scrolls past the sections

SOLVE
Occasional Contributor

Hey there! 

 

Been struggling to get this working. We've got a single page with a navigation that uses anchored links to other places of the page.

 

When the user is in each section, I'd like the menu to use the link's hover state, so the user knows which section they're in. 

 

I've looked at a number of guides online and haven't been able to get it to work! Any help would be much appreciated please Smiley Happy 

 

The page can be found here.

CSS
Reply
0 Upvotes
1 Accepted solution

Accepted Solutions
Highlighted
Esteemed Contributor

Hey @gio-nab 

 

This is a fun one!

So depending on how familiar you are with JS/jQuery this could be extremely easy.

Included in your webiste ina JS file named pillar_slide.min.js, this is the file that has the scroll animation function.

 

First thing you'll want to do is create a CSS class that mimics the hover state. See the CSS below:

 

.custom-menu-primary .hs-menu-wrapper > ul > li > a.is-active {
    color: #00025e;
    border-bottom: 2px solid #00025e;
    transition: border-color .125s cubic-bezier(.4,0,.2,1);
}

This styling is pulled directly from your current hover state. I added the class ".is-active", change this class name as needed to avoid any naming issues.

 

 

Now we can create some JS.

Since we now know how the browser is listening to the clicks we can just mimic that by copying the code from the pillar_slide  ("think smarter not harder" as they say):

 

$('a[href*="#"]').not('[href="#"]').not('[href="#0"]').click(function(a) { // we copied this from the existing listener function
// first prevent the default funcitonality of the browser
a.preventDefault(); // now that we've captured the click we want to remove the "is-active" class from all of the navi links $('a[href*="#"]').not('[href="#"]').not('[href="#0"]').removeClass('is-active'); // now that the class has been removed from all links we will want to apply 'is-active' to the clicked link. this is done using THIS $(this).addClass('is-active'); });

This can be added directly into your pillar_slide.min.js, or added to a custom module.

 

 

I've created a CodePen here with a live working version.

 

This is just a step in the right direction really hope this helps! 

7 Replies 7
Esteemed Advisor

Hi @gio-nab ,

 

How is your menu "jumping" to the sections? does the page reload to the section that corresponds to the clicked link? or is it a smooth scroll.

 

I ask because a simple jump link links to a section's ID (<a href="#section_id></a>) and the pag reloads with that ID appended to the url:

www.website.com/page#section_id

if that is th case then you could us some javascript to identify the section_id in the url, and us logic to match it to th appropriate link, adding a class to the link that gives the link the appropriate styling.

If it is a scroll effect than th url probably won't change, but there will be an on click javascript/jquery function. You can edit that function to assign a class to $(this), the link that was clicked.

 

let me know if that helps.

- Jonathan Sumner
Reply
0 Upvotes
Occasional Contributor

Hey Jsum,

 

You can take a look at the preview here: https://preview.hs-sites.com/_hcms/preview/template/multi?is_buffered_template_layout=true&portalId=...

 

The page uses javascript to do some smooth scrolling to the sections of the page. Do you know what we could use to change the active state please (not just for clicking on the menu item, but also when scrolling down the page?)

 

Thank you!

Reply
0 Upvotes
Highlighted
Esteemed Contributor

Hey @gio-nab 

 

This is a fun one!

So depending on how familiar you are with JS/jQuery this could be extremely easy.

Included in your webiste ina JS file named pillar_slide.min.js, this is the file that has the scroll animation function.

 

First thing you'll want to do is create a CSS class that mimics the hover state. See the CSS below:

 

.custom-menu-primary .hs-menu-wrapper > ul > li > a.is-active {
    color: #00025e;
    border-bottom: 2px solid #00025e;
    transition: border-color .125s cubic-bezier(.4,0,.2,1);
}

This styling is pulled directly from your current hover state. I added the class ".is-active", change this class name as needed to avoid any naming issues.

 

 

Now we can create some JS.

Since we now know how the browser is listening to the clicks we can just mimic that by copying the code from the pillar_slide  ("think smarter not harder" as they say):

 

$('a[href*="#"]').not('[href="#"]').not('[href="#0"]').click(function(a) { // we copied this from the existing listener function
// first prevent the default funcitonality of the browser
a.preventDefault(); // now that we've captured the click we want to remove the "is-active" class from all of the navi links $('a[href*="#"]').not('[href="#"]').not('[href="#0"]').removeClass('is-active'); // now that the class has been removed from all links we will want to apply 'is-active' to the clicked link. this is done using THIS $(this).addClass('is-active'); });

This can be added directly into your pillar_slide.min.js, or added to a custom module.

 

 

I've created a CodePen here with a live working version.

 

This is just a step in the right direction really hope this helps! 

Occasional Contributor

Hey @Kevin-C !

 

Amazing, this is super - thank you!

 

I'd love if I could ask you a couple of follow-up questions in regards to this please?

 

1. This works perfectly for when the menu items are clicked, but what if a user clicks a menu item, then scrolls into the next section - how can we make the next section use the active class, and remove it from the previous section?

2. Sometimes (randomly, not always) the anchor links end up in the wrong position, e.g. just above the title text, instead of the seciton - then when I try again, it often corrects itself. Any idea what could cause this? It looks as though it's when I click on the first link, then onto another link!

 

Much appreciated! Smiley Happy 

 

Reply
0 Upvotes
Esteemed Contributor

Sorry for my delay!

 

So with this new requirement I would approach this a little differently.

 

So what might work best is to build a function or use a plugin that listens to the window/document scroll event and given its location it highlights the approcpriate link, rather than relying on a click event!

 

Since the scrollTo animation is already in place this approach will work for both scroll animation and manual scrolling!

 

This fiddle demonstrats and provides some viable code to begin with.

 

I'll try to dive in and write up a function that will work a little later if I can!

 

Hope this helps!

Occasional Contributor

Hey @Kevin-C !

 

Thank you for the reply, that would be amazing, I'd really appreciate if you had the time to put together the function for me. Thank you kindly!

 

Reply
0 Upvotes
Esteemed Advisor

Hey @gio-nab ,

 

@Kevin-C 's example  looks like a good fit and tailored to your specific page, I would try it.

- Jonathan Sumner