0

I have a fixed div containing an image that scrolls with the user from the top of the page. As new content divs enter the viewport I want the image to change.

I found a related piece of code that will change the image based on how far a user scrolls in pixels. This works, but only if the viewport is a specific size, else the image changes too early/late:

Example

I'm trying to modify this so that the change is instead based on when another div comes into view so that it works no matter the screen size (content div heights are set with relative units). I think this can be done if the other divs positions are saved to a variable and then used in place of the pixel values in the above code. However I can't seem to get this right, probably because I've not calculated the other div positions correctly.

$("#display1").fadeIn(1000);
$(window).scroll(function() {
  var pos = $(window).scrollTop();
  var first = $("#first").offset();
  var second = $("#second").offset();
  if (pos < first) {
    hideAll("display1");
    $("#display1").fadeIn(1000);
  }
  if (pos > first && pos < second) {
    hideAll("display2");
    $("#display2").fadeIn(1000);
  }
  etc...
});

function hideAll(exceptMe) {
  $(".displayImg").each(function(i) {
    if ($(this).attr("id") == exceptMe) return;
    $(this).fadeOut();
  });
}
G Dubz
  • 1

2 Answers2

0

You should try

getBoundingClientRect()

JS method, since It gets the position of the elements relative to the viewport. Check this answer: https://stackoverflow.com/a/7557433/4312515

0

Here is a quick proof of concept of changing a background image based on an element getting into view.

There are three divs. When the third div reaches the bottom of the viewport it will change the color of the background. When the third divs scroll out of the view again the background color is reset to its initial color.

Normally you should debounce the scroll event to prevent slowing down the UI. For this example I didn't debounce the event so you get a better sense of when the background is changed.

const
  card3 = document.getElementById('card3'),
  background = document.getElementById('background');
  
let
  isCardVisible = false;
  
function checkDivPosition() {
  const
    cardTopPosition = card3.getBoundingClientRect().top,
    viewportHeight = document.documentElement.clientHeight,
    isInView = cardTopPosition - viewportHeight < 0;
    
  if (isInView && !isCardVisible) {
    background.style.backgroundColor = 'rebeccapurple';
    isCardVisible = true;
  } else if (!isInView && isCardVisible) {
    background.style.backgroundColor = 'orange';
    isCardVisible = false;
  }
}


function onWindowScroll(event) {
  checkDivPosition();
}
  
window.addEventListener('scroll', onWindowScroll);
body {
  margin: 0;
}

.background {
  height: 100vh;
  opacity: .2;
  position: fixed;
  transition: background-color .3s ease-out;
  width: 100vw;
}

.card {
  border: 1px solid;
  height: 100vh;
  width: 100vw;
}
.card + .card {
  margin-top: 5vh;
}
<div id="background" class="background" style="background-color:orange"></div>

<div class="card">
  Card 1
</div>
<div class="card">
  Card 2
</div>
<div id="card3" class="card"> 
  Card 3.
</div>
Thijs
  • 2,281
  • 2
  • 12
  • 21
  • This code when used in my text editor works when scrolling down (It changes the background color) but when scrolling back up it doesn't change the background color back to "Orange" which it should! – Ashique Desai Apr 08 '20 at 08:10
  • This code was working only partially before when copied in my text editor and run on my machine. It would change the background color when scrolling down but wouldn't change it again when scrolled up. The solution: Instead of "viewportHeight = document.documentElement.clientHeight" use "viewportHeight = window.innerHeight – Ashique Desai Apr 09 '20 at 04:59