4

An intersection observer is set up on an element. When the element is scrolled past a certain point, the intersection observer handler is fired as expected. However, if a button is clicked to scroll the element past that same point, the handler is not fired.

Why is that? Is there a way to force the handler to be fired when using scrollTo/scrollIntoView?

const container = document.getElementById("container");
const hello = document.getElementById("hello");
const button = document.getElementById("button");

const options = {
  rootMargin: "-100px 0px 0px 0px",
  threshold: 1
}

const handleIntersect = entries => {
  entries.forEach((entry) => {
    console.log("handleIntersect")
  });
};

const observer = new IntersectionObserver(handleIntersect, options);

observer.observe(hello);

button.addEventListener("click", () => {
  container.scrollTo({
    top: 120
  });
})
body {
  margin: 0;
}

#container {
  background-color: #ddd;
  height: 400px;
  overflow-y: auto;
}

.inner-container {
  height: 100px;
  border-bottom: 1px solid #bbb;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  text-align: right;
}

#button {
  margin: 40px;
  font-size: 20px;
}

#hello {
  display: inline-block;
  padding: 20px 40px;
  background-color: blue;
  color: white;
  margin-top: 150px;
  margin-bottom: 500px;
}
<div id="container">
  <div class="inner-container">
    <button id="button">Scroll</button>
  </div>
  <div id="hello">Hello</div>
</div>
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • Running your snippet I get the log when I click the button (Both from Chrome and Firefox on macOS) – Kaiido Aug 30 '22 at 23:43
  • @Kaiido Strange that it's happening here on StackOverflow in this embedded snippet. Could you try here: https://jsbin.com/gokuwilota/1/edit?html,css,js,output – Misha Moroshko Aug 31 '22 at 02:51
  • I still see it fire, when it comes from the top. Not when it comes from the bottom but I don't see it from scrolling manually until there either in that direction. – Kaiido Aug 31 '22 at 11:59
  • Tested it on Chrome 104, and it consistently fires when scrolling manually in both directions when the bottom of the blue element is crossing the line. What browser are you using @Kaiido? – Misha Moroshko Aug 31 '22 at 12:22
  • Still both l'attestation stable Chrome and Firefox on macOS – Kaiido Aug 31 '22 at 13:38

2 Answers2

0

remove rootMargin from options object and it will intersect, also you can decide percentage of visibility, if callback should be fired if even 50% is visible, you can provide inside options object

{ threshold: 0.5} 

and so all...

n1koloza
  • 539
  • 5
  • 11
0

I don't know if this solves your problem, But What I think is when we have scrollIntoView linked to a button we specify a value to the position of scrollbar if the button is clicked, for example when we click a button which has a scrollTo() function we expect the scrollbar to be at a specific place but that doesn't mean the scrollbar is sliding to the place which looks similar to the action that happens when we scroll the mouse.

In other words the intersection API fires an even when you cross a particular position or a point, however it does not fire an even if you just skip crossing the point and jump directly the desired position which happens when you use scrollIntoView,

In case you wonder that when you use scrollTo() to smooth scroll the webpage, you can visually see the scroll bar sliding to the particular point as if it passes the threshold point, however it is not the case, behind the scene the scrollbar just skip all the content and moves directly the specified position.

One way to counter the problem (not efficient) is to use looping, try looping from the current page offset value to your target value instead of hardcoding the value to the scrollIntoView() , it does gives you the desired output but the scrolling animation will be poor and it loses it's objective.

M NARESH
  • 142
  • 1
  • 7