skip to Main Content

This is the jQuery code I’m trying to work with, found in this answer:

$(document).ready(function(){
    $(window).scroll(function(){
    var light_pos = $('.white_div').offset().top;
    var light_height = $('.white_div').height();
    var menu_pos = $('.menu-item').offset().top;
    var scroll = $(window).scrollTop();

    if(menu_pos > light_pos && menu_pos < (light_pos + light_height)) {
        $('.menu-item').addClass('menu_black');
      $('.menu-item').removeClass('menu_white');
    }
    else {
        $('.menu-item').removeClass('menu_black');
      $('.menu-item').addClass('menu_white');
    }

  })
})

The navigation is fixed, so it follows you when you scroll down. But the issue I’m having is that it needs to change colors based on the background below it. As in, some sections are white, others are dark and I need the navigation link to reflect that. However, the code doesn’t seem to be working for my structure. After it loads and lands on the dark background, the text is white, as it should be. And it switches to dark on the next white div. But after that, it just changes back to white and doesn’t follow the classes of divs at all.

What can I do to fix this? Thank you!

Adding a snippet:

$(document).ready(function(){
    $(window).scroll(function(){
    var light_pos = $('.white_div').offset().top;
    var light_height = $('.white_div').height();
    var menu_pos = $('.menu-item').offset().top;
    var scroll = $(window).scrollTop();

    if(menu_pos > light_pos && menu_pos < (light_pos + light_height)) {
        $('.menu-item').addClass('menu_black');
      $('.menu-item').removeClass('menu_white');
    }
    else {
        $('.menu-item').removeClass('menu_black');
      $('.menu-item').addClass('menu_white');
    }

  })
})
.menu-item {
position: fixed;
}

.menu_white {
    color: #fff;
}

.menu_black {
    color: #000;
}

.dark_div {
background: #000;
/* added height & styling just for preview */
height: 150px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}

.white_div {
background: #fff;
/* added height & styling just for preview */
height: 150px;
display: flex;
justify-content: center;
align-items: center;
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="menu-item menu_white" href="#">Link</a>

<div class="dark_div">Dark Background</div>
<div class="white_div">White background</div>
<div class="white_div">White background</div>
<div class="white_div">White background</div>
<div class="dark_div">Dark Background</div>

<div style="height: 500px"></div>

2

Answers


  1. You do not change the white_div so (light_pos + light_height) never changes after the first div.

    First div: 307 > 157 && 307 < (157 + 150) true

    onto the next white which is NOT at 157

    309 > 157 && 309 < (157 + 150) false

    The method I found was not trivial. I do not have time to improve it right now though. At least I am speeding things up by finding the scroll direction. This will however handle black/white/black/white

    $(function() {
      // Save the div's position (remove or repeat this if the divs are dynamically added)
      let $whiteDivs = $('.white_div');
      let $blackDivs = $('.black_div');
      let positions = [];
    
      // Calculate positions for white divs and black divs
      $whiteDivs.each(function(index) {
        let $this = $(this);
        let light_pos = $this.offset().top;
        let light_height = $this.height();
        let $nextBlackDiv = $blackDivs.eq(index);
        positions.push({
          whitePos: light_pos,
          whiteHeight: light_height,
          blackDiv: $nextBlackDiv
        });
      });
    
      let prevScrollTop = $(window).scrollTop();
    
      $(window).scroll(function() {
        let menu_pos = $('.menu-item').offset().top;
        let scroll = $(window).scrollTop();
        let currentWhiteDiv = null;
        let nextBlackDiv = null;
    
        // Determine scroll direction
        let scrollDirection = scroll > prevScrollTop ? 'down' : 'up';
    
        // Iterate through positions based on scroll direction using a for loop
        for (let i = 0; i < positions.length; i++) {
          let position = positions[i];
          let isWithinWhiteDiv = menu_pos > position.whitePos && menu_pos < (position.whitePos + position.whiteHeight);
    
          if ((scrollDirection === 'down' && isWithinWhiteDiv) || (scrollDirection === 'up' && menu_pos > position.whitePos)) {
            currentWhiteDiv = $whiteDivs.eq(i);
            nextBlackDiv = position.blackDiv;
            break; // Exit the loop when the desired elements are found
          }
        }
    
        // Update the menu class based on the currentWhiteDiv and nextBlackDiv
        if (currentWhiteDiv && nextBlackDiv) {
          $('.menu-item').removeClass('menu_black menu_white');
          currentWhiteDiv.closest('.menu-item').addClass('menu_white');
          nextBlackDiv.closest('.menu-item').addClass('menu_black');
        } else {
          $('.menu-item').removeClass('menu_black').addClass('menu_white');
        }
    
        prevScrollTop = scroll;
      });
    });
    .menu-item {
      position: fixed;
    }
    
    .menu_white {
      color: #fff;
    }
    
    .menu_black {
      color: #000;
    }
    
    .dark_div {
      background: #000;
      /* added height & styling just for preview */
      height: 150px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
    }
    
    .white_div {
      background: #fff;
      /* added height & styling just for preview */
      height: 150px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #000;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <a class="menu-item menu_white" href="#">Link</a>
    
    <div class="dark_div">Dark Background</div>
    <div class="white_div">White background</div>
    <div class="white_div">White background</div>
    <div class="white_div">White background</div>
    <div class="dark_div">Dark Background</div>
    
    <div style="height: 500px"></div>
    Login or Signup to reply.
  2. I think I found a solution to your problem. First of all by getting this $('.white_div').height(); it doesn’t really serve you because it is just one unique height of your div.

    Therefore, what you really need is the sum of heights of your three divs with the white background.
    In order to achieve that, I saved the length of all your white_divs to a variable named light_height_divs which is the quantity of white divs inside your DOM.

    I also changed your if condition inside your jquery code by replacing this if(menu_pos > light_pos && menu_pos < (light_pos + light_height)) { =>
    if(menu_pos > light_pos && menu_pos < (light_pos + light_height_divs*light_height)) { multiply the quantity of white divs with the height of one given div.

    $(document).ready(function(){
        $(window).scroll(function(){
        var light_pos = $('.white_div').offset().top;
    
        var light_height_divs = $('.white_div').length;
        var light_height = $('.white_div').height();
        var menu_pos = $('.menu-item').offset().top;
        var scroll = $(window).scrollTop();
    
        if(menu_pos > light_pos && menu_pos < (light_pos + light_height_divs*light_height)) { //
    
            $('.menu-item').addClass('menu_black');
          $('.menu-item').removeClass('menu_white');
        }
        else {
            console.log("doesn't enter");
            $('.menu-item').removeClass('menu_black');
          $('.menu-item').addClass('menu_white');
        }
    
      })
    })
    .menu-item {
    position: fixed;
    }
    
    .menu_white {
        color: #fff;
    }
    
    .menu_black {
        color: #000;
    }
    
    .dark_div {
    background: #000;
    /* added height & styling just for preview */
    height: 150px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #fff;
    }
    
    .white_div {
    background: #fff;
    /* added height & styling just for preview */
    height: 150px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #000;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <a class="menu-item menu_white" href="#">Link</a>
    
    <div class="dark_div">Dark Background</div>
    <div class="white_div">White background</div>
    <div class="white_div">White background</div>
    <div class="white_div">White background</div>
    <div class="dark_div">Dark Background</div>
    
    <div style="height: 1000px"></div>

    I hope that helps you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search