How to add active class on scroll in jQuery?

Here's a demo in Plunker.

I have a few div elements with data-msid ('1', '2', '3'), and each one has a corresponding li in footer with data-msidatrr ('1', '2', '3').

PROBLEM:

I want to add active class on footer li when the user scrolls and the corresponding div becomes visible in viewport.

EXAMPLE:

When id='first' data-msid="1" appears in the viewport, li data-msidatrr="1" in footer should have an active class, and so on for the rest of the div and footer li.

Here's my jQuery code:

$(function(){
    $.fn.isOnScreen = function(){
        var win = $(window);

        var viewport = {
            top : win.scrollTop(),
            left : win.scrollLeft()
        };

        viewport.right = viewport.left + win.width();
        viewport.bottom = viewport.top + win.height();

        var bounds = this.offset();
        bounds.right = bounds.left + this.outerWidth();
        bounds.bottom = bounds.top + this.outerHeight();

        return ( ! (
            viewport.right < bounds.left ||
            viewport.left > bounds.right ||
            viewport.bottom < bounds.top ||
            viewport.top > bounds.bottom
        ));
    }; /* END $.fn.isOnScreen */

    $( "#container" ).scroll(function() {
        console.log('scrlling');

        $.each( $('#container>div'), function(i, left) {
            console.log(i);
            var msid = $(left).attr('data-msid');
            console.log($(left).attr('data-msid'));
            console.log($('#first').isOnScreen());
            $('.fC[data-msidatrr=]+msid').addClass('active');
        })
    });
}) /* END $(function() */

Answers 1

  • Here's a working JSFiddle.

    First, you have some errors in your HTML and jQuery:

    <!-- wrong div id -->
    <div id='second' data-msid="12">
    <!-- correct div id -->
    <div id='second' data-msid="2">
    
    <!-- wrong -->
    <li class='item data-msidatrr="3"'>third</li>
    <!-- correct -->
    <li class='item' data-msidatrr="3">third</li>
    

    // wrong
    $('.fC[data-msidatrr=]+msid').addClass('active');
    // correct
    $(".fC li[data-msidatrr='" + msid + "']").addClass('active');
    

    Second, consider using this neat function to detect if a div is visible in your #container on scroll: (credits to reference)

    function isScrolledToView(el) {
        var container = document.getElementById('container').getBoundingClientRect();
        var div = el.getBoundingClientRect();
    
        console.log('container.top = '+container.top+'; container.bottom = '+container.bottom)
    
        return ((div.top >= container.top) && (div.top <= container.bottom));
    }
    

    The code above will simplify your code, since you won't be needing $.fn.isOnScreen anymore.


    BONUS (optional):

    • enclose your HTML element attributes with double quotes, not single quotes:
      • id="container" NOT id='container'
    • in the case of your third and fourth div, they will be "active" at the same time because of their short height, so you might want to do something with it.

Related Articles