Reputation: 93
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");
}
});
});
Upvotes: 2
Views: 15057
Reputation: 6283
Here are following 3 helpful similar link:-
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.
Upvotes: 1
Reputation: 5170
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');
}
});
});
});
Upvotes: 4