Joe Consterdine Joe Consterdine - 1 year ago 116
jQuery Question

Active Link On Scroll Delay

I've made an active link for when scrolling on each section.

The problem is:

  1. It seems to change slightly inside the section rather than the scroll hits the very top (I think it may be to do with padding).

  2. Section A is highlighted before entering the section.

How could I resolve these two issues?

<!DOCTYPE html>
<meta charset="utf-8">
<div class="header pd">
<li>Section A</li>
<li>Section B</li>
<li>Section C</li>
<li>Section D</li>
<div class="section-a pd">
<h3>Section A</h3>
<div class="section-b pd">
<h3>Section B</h3>
<div class="section-c pd">
<h3>Section C</h3>
<div class="section-d pd">
<h3>Section D</h3>
<script src="" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script type="text/javascript">

var navOffset = $("nav").offset();

$(document).on("scroll", function(){
var scrollTop = $(document).scrollTop();

if(scrollTop > {
} else {

$(document).on("scroll", function(){
var scrollTop = $(document).scrollTop();

var sectionA = $(".section-a").offset().top;
var sectionB = $(".section-b").offset().top;
var sectionC = $(".section-c").offset().top;
var sectionD = $(".section-d").offset().top;
var activeSection;

if(scrollTop < sectionB) {
activeSection = $("nav>ul>li:nth-child(1)");
} else if (scrollTop < sectionC){
activeSection = $("nav>ul>li:nth-child(2)");;
} else if(scrollTop < sectionD) {
activeSection = $("nav>ul>li:nth-child(3)");;
} else {
activeSection = $("nav>ul>li:nth-child(4)");;







Answer Source

You have to check for a scroll range by subtracting the current scroll top minus the current section top coordinate. When they are equal then that subtraction will equal zero and that's how you know which section is within view. The problem is that is nearly impossible to catch when they are exactly zero therefore you have to check when the subtraction is approximately zero using a range as follows:

//Checking when the subtraction is between 0 and 200 
if ((scrollTop - sectionA) > 0 && (scrollTop - sectionA) < 200) {
    activeSection = $("nav>ul>li:nth-child(1)");
} else if ((scrollTop - sectionB*.8) > 0 && (scrollTop - sectionB*.8) < 200) {
    activeSection = $("nav>ul>li:nth-child(2)");
} else if ((scrollTop - sectionC*.8) > 0 && (scrollTop - sectionC*.8) < 200) {
    activeSection = $("nav>ul>li:nth-child(3)");
} else if ((scrollTop - sectionD*.8) > 0 && (scrollTop - sectionD*.8) < 200) {
    activeSection = $("nav>ul>li:nth-child(4)");

In my example I'm checking that current scroll difference is > 0 and < 200. So between zero and 200. When users scrolls up or down the scroll coordinates could skip if the user is scrolling fast. I picked 200 as the upper range because numbers less than that will make the range too small and some or all the numbers in that smaller range might be skipped if the user is scrolling very fast and the if statement might never be evaluated and hence the section indicator will not to be highlighted. You could choose a bigger number to increase the scroll range and hence increase the chances of detecting that the current scroll position is at the currently visible section. Avoid using numbers too big however, or the user will scroll right beyond the section within view and it won't become highlighted in the nav area.

Furthermore, notice that I'm multiplying times .8; or 80% of the section top coordinate value. This is to compensate for the height of the nav section. Without this, the nav section indicator will not be highlighted unless you virtually scroll pass the current section since the current section has not yet been scrolled to top. This should help with both your problems or at least point you in a good direction (I hope).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download