For a fixed header I add/remove an active class to the anchors like this:
// Store basic variables:
var win = $(window),
sec = $('section'),
nav = $('nav'),
anc = $('nav a'),
pos = nav.offset().top, // Distance of navigation to top of page
arr = sec.map(function(){return $(this).offset().top}).get(); // Distance of each section to top of page in an array
// Make function to add/remove classes:
win.scroll(function(){
var t = win.scrollTop(); // Distance of window top to top of page
t > pos ? nav.addClass('sticky') : nav.removeClass('sticky'), // Compare viewport top with top of navigation
// Compare each section position:
$.each(arr, function(i, val) {
(t >= Math.floor(val) && t < (val + sec.eq(i).outerHeight(true))) ? anc.eq(i-1).addClass('active')
: anc.eq(i-1).removeClass('active')
})
})
On some sections however at the very beginning of the section (i.e. after clicking the anchor and not scrolling further) the active class of the previous section (which is not in viewport anymore) won't get removed. Most probably due to calculations returning significant digits?
How can I get the calculations right so only the current section in viewport gets its anchor highlighted?
While I found some very weird behaviour during debugging this, it's as simple as substracting one pixel from the height of the section:
t >= val && t < (val + sec.eq(i).outerHeight(true) -1) ? ...
The rounding now happens directly inside var arr: return Math.floor($(this).offset().top)
1824 >= 912 && 1824 < (912 + 912)
So I had to substract 1px to make this true after all.
Which gets weird when rounding down doesn't work on it. In my fiddle I put the height of the sections to 912.453125px and .outerHeight()
returned 912 but rounding it down with Math.floor()
still seemed to return the fractions although it wouldn't print. (See this fiddle, where, when you go to section two and press the debug button, the calculation would be the above example)
So yeah, whatever. I'd like to have a more logical solution but substracting a pixel works.