'IntersactionObserver() only observes the first element of a row instead of all
I'm experimenting with IntersectionObserver(), and it's behaving weirdly: I'm using a very simple layout, just 8 images in the same div with flexbox, using wrap, so basically the 8 images are positioning themself in different rows, according to the size of the viewport. I'm applying a filter class (which adds a blur filter) to each element first and then removing it when they are displayed on the screen:
HTML:
<div class="flex--cont">
<div class="box box-2">
<img src="img/1.jpg" alt="" class="img img-1">
</div>
<div class="box box-1">
<img src="img/2.jpg" alt="" class="img img-2">
</div>
<div class="box box-3">
<img src="img/3.jpg" alt="" class="img img-3">
</div>
<div class="box box-4">
<img src="img/4.jpg" alt="" class="img img-4">
</div>
<div class="box box-5">
<img src="img/5.jpg" alt="" class="img img-5">
</div>
<div class="box box-6">
<img src="img/6.jpg" alt="" class="img img-6">
</div>
<div class="box box-7">
<img src="img/7.jpg" alt="" class="img img-7">
</div>
<div class="box box-8">
<img src="img/8.jpg" alt="" class="img img-8">
</div>
</div>
JAVASCRIPT
const allImage = Array.from(document.querySelectorAll(".img"));
allImage.forEach((img) => img.classList.add("filter"));
const removeFilter = function (entries, observer) {
const [entry] = entries;
const image = entry.target;
image.classList.remove("filter");
};
const ImageObserver = new IntersectionObserver(removeFilter, {
root: null,
threshold: 0.15,
});
allImage.forEach((img) => ImageObserver.observe(img));
The thing is that the observer actually only observes the very first element of each row, so if I have 2 rows, it only gets the 1st and the 5th image, if I have 3 rows it gets the 1rst, the 4th and the 7th image and so on. I do have applied it to all of the images. Why is it doing that? Thanks for your answers!
Solution 1:[1]
Only the first one was changing because that was all you were targeting in the change color function by destructuring only the first array element:
const [entry] = entries;
However, the InteractionObserver callback is not called per entry but for all entries that are triggered simultaneously; hence the entries array contains all of the items being observed and you need to check the isIntersecting property like this:
const changeColor = function(entries) {
entries.forEach(entry => {
if(entry.isIntersecting) {
entry.target.style.background = 'blue';
} else {
entry.target.style.background = 'red';
}
})
}
From the MDN docs
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | alexanderdavide |
