skip to Main Content

I have an element that has a complex position on a page, meaning that it could have been transformed with css, it could be in a parent that has a sticky position etc…
Now, how can I compute at what value of document.scrollingElement.scrollTop my element will first appear, and at what value it will disappear ?

If you run this code, when the element first enters the screen you will see in the console at which scroll position it did so, and then when it exited. I need to know those two values at any point in time, no matter how much scroll has already been applied, if the window has been resized etc…

let entry = false;
let exit = false;
window.addEventListener("scroll", () => {
  let y = element.getBoundingClientRect().y
  if (!entry && y < window.innerHeight && y + element.clientHeight >= 0) {
    entry = true
    console.log("element enters the screen at", window.scrollY);
  }
  if (entry && !exit && y + element.clientHeight < 0) {
    exit = true;
    console.log("element exits the screen at", window.scrollY);
  }
})

setInterval(()=>{
  document.scrollingElement.scrollTop++
},5)
html,
body {
  margin: 0px;
}

#parent {
  height: 500vh;
}

#space {
  height: calc(100vh + 19px);
}

#sticky {
  height: 275vh;
  top: 0px;
  position: sticky;
}

#element {
  width: 100px;
  height: 200px;
  background-color: blue;
  position: absolute;
  top: 100px;
  left: 40px;
  transform: translate(100px, -30px)
}
<div id="parent">
  <div id="space"></div>
  <div id="sticky">
    <div id="element"></div>
  </div>
</div>

I have tried using element.getBoundingClientRect().y, I have computed the initial distance from the top of the document to the top of the element by summing all of its parents’ "offsetTop" values . But for example when the element is contained in a parent that has a sticky position, and this parent is in the "fixed" state, scrolling will totally change this total offset value and mess everything up.

2

Answers


  1. I would recommend you to get the scroll Y property from the window, instead of the element. Also, to detect if the user has scrolled I would implement a onscroll event listener.

    Check the code below:

    //elem represents the element that you want to hide
    
    let elem = document.querySelector(...)
    
    //the onscroll event will execute when the user scrolls
     window.onscroll = () => {
    
     //200 is a example value, but you can put any scrollY position by testing when do 
     //you want to hide the element
    
     if(window.scrollY === 200) {
    
      //this is a example of how I would hide the element via CSS but you can 
      //use another method just as changing the opacity.
      elem.style.display = "none"
    
     }
    
    }
    

    If you want to know more about the onscroll event you can go to the documentation.
    If you want to know more about the scrollY property you can go to the documentation.

    Also, if you don´t want to hide the element by using display:none; you can use opacity:0; or visibility:hidden;. Check the differences here.

    Login or Signup to reply.
  2. What do you want to do with the scrollTop value?

    1. If you want to do something to the element when it has been scrolled off-screen or appears in-screen

    Then you don’t have to calculate this value yourself. You can use the IntersectionObserver API: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

    new IntersectionObserver(
      (entries, observer) => {
        for (const entry of entries) {
          const isOutside = (entry.intersectionRatio === 0);
          if (isOutside) {
            // Do something when it has scrolled off-screen
          } else {
            // Do something when it has scrolled in-screen
          }
        }
      },
      {
        threshold: 0.0001 // Because sometimes a pixel in not visible on screen but the intersectionRatio is already 0
      }
    );
    

    2. Or if you want to do something to the element when it is a certain amount of pixels away from the screen boundaries

    You might want to use the optional rootMargin option of the IntersectionObserver:
    https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin

    rootMargin: `1000px 50px 20px 80px`
    

    3. Or if you want to do something to the element when it is fully visible in-screen

    You can increase the optional threshold option of the IntersectionObserver to 1:
    https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/thresholds

    threshold: 1
    

    4. But if you still want to calculate the scrollTop yourself

    You must add the current scrollTop value of the scrolling element to the element.getBoundingClientRect().y value.

    const y = scrollingElement.scrollTop + element.getBoundingClientRect().y;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search