What is the fastest way to track list of top visible divs under the fixed header?

I'm working on layout, which you may visually imagine using a link below:

Layout

Fixed header is a div with position: fixed. Which means, that scrolling process hides elements under it (that's why it's transparent on my image for illustration purposes). I need to track a list of vertically top elements (other divs) on a page, which are still visible. Using my layout example, I need a list of red elements. They may be positioned in any way.

Expected result is JavaScript function, which returns an array of elements. Behind the scenes, the solution should definitely track window.onScroll event and somehow effectively maintain ability to fetch the result in the fastest possible way.

Answers 1

  • I created the function getDivs which will return the jQuery object with the specific divs.

    You can edit the $allDivs variable inside the function to any jQuery object you wish to check

    Please check my snippet below:

    var
    $allDivs = $('#container > .column > div'), // Divs you want to check
    $header = $('#header');
    
    function getDivs() {
      return $allDivs
      .filter(function() {
        var
        $this = $(this),
        top = parseInt($this.offset().top, 10),
        bottom = top + $this.outerHeight(),
        scrTop = $header.offset().top + $header.outerHeight();
    
        if (top <= scrTop && bottom >= scrTop)
          return true;
        else
          return false;
      });
    }
    
    $allDivs.removeClass('under');
    getDivs()
    .addClass('under');
    
    $(window).scroll(function() {
      $allDivs.removeClass('under');
      
      getDivs()
      .addClass('under');
      
    })
    body {
      height: 1300px;
    }
    
    #header {
      width: 100%;
      padding: 50px;
      box-sizing: border-box;
      position: fixed;
      top: 0px;
      left: 0px;
      background: rgba(0, 0, 0, 0.3);
    }
    
    .column {
      float: left;
      display: flex;
      flex-flow: column wrap;
      justify-content: flex-start;
      align-items: flex-start;
      align-content: flex-start;
    }
    
    .column > div {
      height: 100px;
      width: 100px;
      border: 1px solid green;
      flex: 1 1 100px;
    }
    
    #col1 { margin: 100px 0 0; }
    
    #col3 { margin: 30px 0 0; }
    
    #col1 > div { flex: 1 1 75px; }
    
    #col2 > div { flex: 1 1 200px; }
    
    .under { background: red; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="header">
      Header
    </div>
    <div id="container">
      <div id="col1" class="column">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
      <div id="col2" class="column">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
      <div id="col3" class="column">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
    </div>


Related Articles