1

I'm trying to change the color of a fixed element (.logo) when scrolling on top of a dark image (.image). I came across this solution:

Detect when static element overlaps fixed element position on scroll

Which only works for a single image. But what if I want to change the color of the fixed element when scrolling passed all the images with the image class by using querySelectorAll?

I tried to solve this with a forEach but the fixed element only changes color on the last image. Can somebody explain this behaviour, in my mind this should work?

https://codepen.io/bosbode/pen/GaJNKr

HTML

<p class="logo">Logo</p>
<div class="image"></div>
<div class="image"></div>

CSS

body {
  text-align: center;
  height: 100%;
  font-size: 1.5rem;
}

.image {
  width: 800px;
  height: 600px;
  background: blue;
  margin: 100px auto;
}

.logo {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translate(-50%, 0)
}

JavaScript

const logo = document.querySelector('.logo');
const images = document.querySelectorAll('.image');

window.addEventListener('scroll', function () {

  const a = logo.getBoundingClientRect();

  images.forEach((item, index) => {

    const b = item.getBoundingClientRect();

    if (a.top <= (b.top + b.height) && (a.top + a.height) > b.top) {
      logo.style.color = 'white';
    } else {
      logo.style.color = 'black';
    }
  })

});

1 Answers1

0
for (var i = 0; i < images.length; i++) {
    var item = images[i]
    let b = item.getBoundingClientRect();

    if (a.top <= (b.top + b.height) && (a.top + a.height) > b.top) {
        logo.style.color = 'white';
        break;
    } else {
        logo.style.color = 'black';
    }
};

Updated content:
1. For this solution, I need using break statement in loop, so I am using for instead of foreach
2. We need break if logo is inside in every image.

WHY?:
If logo is inside image1, then its' color can be white, but next step, its' color can be black, because logo is not inside image2.

Below code is more readable for this solution:

const logo = document.querySelector('.logo');
const images = document.querySelectorAll('.image');

function isInsideInImages(images, logoPos) {
    for (var i = 0; i < images.length; i++) {
        let imagePos = images[i].getBoundingClientRect();

        if (logoPos.top <= (imagePos.top + imagePos.height) && (logoPos.top + logoPos.height) > imagePos.top) {
            return true;
        }
    };
    return false;
}

window.addEventListener('scroll', function () {

    const a = logo.getBoundingClientRect();

    if (isInsideInImages(images, a)) {
        logo.style.color = 'white';
    } else {
        logo.style.color = 'black';
    }

});
Wang Liang
  • 4,244
  • 6
  • 22
  • 45