Home > Software engineering >  Change link color based on background/class?
Change link color based on background/class?

Time:11-05

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  href="#">Link</a>

<div >Dark Background</div>
<div >White background</div>
<div >White background</div>
<div >White background</div>
<div >Dark Background</div>

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

CodePudding user response:

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  href="#">Link</a>

<div >Dark Background</div>
<div >White background</div>
<div >White background</div>
<div >White background</div>
<div >Dark Background</div>

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

I hope that helps you.

CodePudding user response:

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  href="#">Link</a>

<div >Dark Background</div>
<div >White background</div>
<div >White background</div>
<div >White background</div>
<div >Dark Background</div>

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

  • Related