Dynamically changing Class on Fixed nav item based on page scroll (Single Page Website)

14,757

Solution 1

This works nicely: DEMO

All you need to do is add class="link" to all of your <a> tags, and it will then get given the class "active" when an element with the same ID as the href is reached. (if you want your first link highlighted on page load give it the class active in your HTML)

So for example <a href="#about_us"></a> will be active when <div id="about_us"></div> is reached.

The "-40" is to compensate for the height of the fixed header, so replace/remove it as needed.

// ADDS ACTIVE CLASS TO LINKS WHEN SECTION WITH THE SAME SELECTOR AS THE HREF IS REACHED (CLASS .LINK IS NEEDED ON ALL <a> TAGS)

$(document).ready(function () {
    $(window).scroll(function () {

        var y = $(this).scrollTop();

        $('.link').each(function (event) {
            if (y >= $($(this).attr('href')).offset().top - 40) {
                $('.link').not(this).removeClass('active');
                $(this).addClass('active');
            }
        });
    });
});

Solution 2

Here are following 3 helpful similar link:-

  1. Tutorial
  2. StakoverFlow Link
  3. Fiddle Exmaple

HTML:

<div id="body">
    <div id="header"> This header will turn blue if it moves past that line and stay green BEFORE that line</div>
    <hr/>
    <div id="largebody"></div>
</div>

JAVASCRIPT:

$("#body").scroll( function() {
    var value = $(this).scrollTop();
    if ( value > 120 )
        $("#header").css("border", "1px solid blue");
    else
        $("#header").css("border", "1px solid green");
});

CSS:

body {
    font: 12px arial;
}

#header {
    height: 40px;
    width: 100%;
    position: absolute;
    top: 0px;
    border: 1px solid green;
}

hr {
    position: relative;
    top: 120px;
    margin: 0px;
}

#body {
    overflow: scroll;
    height: 300px;
}
#largebody {
    height: 900px;
}
body {
    padding: 0px;
}

Hope this help you.

Share:
14,757
Tom
Author by

Tom

i do the internet

Updated on June 05, 2022

Comments

  • Tom
    Tom almost 2 years

    Currently i am a little stuck on a problem and cant seem to find a fix.

    I am trying to build a fixed navigation on a site that the active class changes on as you scroll aswell as when you click. Here is a good example of the navigation i am trying to achieve - kiskolabs.com/

    I have almost got it working with the following code, but after the first 2 nav items working as they should, i find that the nav item state does not change in the correct place. Not sure what i have got wrong, but the anchor links still go to the correct place, just the active state does not change after a couple. Any ideas anyone? Below is the code.

    HTML

    <section id="1">
        <nav>
            <ul>
                <li><a href="#1">1</a></li>
                <li><a href="#2">2</a></li>
                <li><a href="#3">3</a></li>
                <li><a href="#4">4</a></li>
            </ul>
        </nav>
        <p>All content here</p>
    </section>
    <section id="2">
        <p>All content here</p>
    </section>
    <section id="3">
        <p>All content here</p>
    </section>
    <section id="4">
        <p>All content here</p>
    </section>
    

    And am using the jquery:

    $(document).ready(function () {
    var $sections = $('section');  // all content sections
    var $navs = $('nav > ul > li');  // all nav sections
    
    var topsArray = $sections.map(function() {
    return $(this).position().top - 300;  // make array of the tops of content
    }).get();                                 //   sections, with some padding to
                                          //   change the class a little sooner
    var len = topsArray.length;  // quantity of total sections
     var currentIndex = 0;        // current section selected
    
    var getCurrent = function( top ) {   // take the current top position, and see which
    for( var i = 0; i < len; i++ ) {   // index should be displayed
        if( top > topsArray[i] && topsArray[i+1] && top < topsArray[i+1] ) {
            return i;
        }
    }
    };
    
    // on scroll,  call the getCurrent() function above, and see if we are in the
    //    current displayed section. If not, add the "selected" class to the
    //    current nav, and remove it from the previous "selected" nav
    $(document).scroll(function(e) {
    var scrollTop = $(this).scrollTop();
    var checkIndex = getCurrent( scrollTop );
    if( checkIndex !== currentIndex ) {
        currentIndex = checkIndex;
        $navs.eq( currentIndex     ).addClass("selected").siblings(".selected").removeClass("selected");
    }
    });
    
    });