Given an animating (transforming) row of images, detect when each one reaches the center so we can make some changes (e.g., adding styling like filter: grayscale
)
I’ve enlisted IntersectionObserver and gotten close. In fact my solution works great in Firefox but only works in Chrome if the mouse is moving and doesn’t work at all in Safari. Even if I tweak the options parameter behavior seems sporadic unless in Firefox.
Codepen
const options = {
root: document.body,
rootMargin: '0% -50% 0% -50%',
threshold: 0,
}
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.style.filter = 'grayscale(0%)'
} else {
entry.target.style.filter = 'grayscale(100%)'
}
})
}, options)
const items = document.querySelectorAll('.img-container img');
items.forEach(img => observer.observe(img))
0
Use requestAnimationFrame() and find the element in the center using elementFromPoint():
const wrapper = document.querySelector('.wrapper');
const images = document.querySelectorAll('.wrapper img');
const updateActiveImage = () => {
const { left, top, width, height } = wrapper.getBoundingClientRect();
const centerX = left + width / 2;
const centerY = top + height / 2;
const imgAtCenter = document.elementFromPoint(centerX, centerY);
images.forEach(img => img.classList.remove('active'));
if (imgAtCenter) {
imgAtCenter.classList.add('active');
}
requestAnimationFrame(updateActiveImage);
};
requestAnimationFrame(updateActiveImage);
body {
background: black;
margin: 0;
}
.wrapper {
overflow: hidden;
}
img {
width: 300px;
height: 300px;
object-fit: cover;
transition: filter 200ms ease-in-out;
&:not(.active) {
filter: grayscale(100%);
}
}
.img-container {
display: flex;
gap: 24px;
animation: marquee 40s linear infinite;
}
@keyframes marquee {
0% {
transform: translateX(0);
}
to {
transform: translateX(calc(-100% - 24px));
}
}
<div class="wrapper">
<div class="img-container">
<img src="https://www.wonderwall.com/wp-content/uploads/sites/2/2020/11/shutterstock_editorial_10552447px.jpg?x=514&y=800&icq=74&sig=639b09155acfa34ee0f71886a1556c55" />
<img src="https://hips.hearstapps.com/hmg-prod/images/gettyimages-1280266077.jpg" />
<img src="https://cdn-0.atwoodmagazine.com/wp-content/uploads/2018/01/Chappell-Roan-2018.jpg" />
<img src="https://e00-marca.uecdn.es/assets/multimedia/imagenes/2022/06/27/16563602316989.jpg" />
<img src="https://www.expressandstar.com/resizer/SxBF0kXCbz34fI7twkxcDR8Rdi4=/1200x0/cloudfront-us-east-1.images.arcpublishing.com/mna/MWUDEBVNBZBYFAQSYYVPEYATGQ.jpg" />
<img src="https://parade.com/.image/t_share/MTk3OTcwMTgwMDE2NDQ5MzA5/lindsay-lohan-nyc-2022.jpg" />
<img src="https://i.pinimg.com/originals/5c/b3/02/5cb302c78b1bb14e57194bdc31e7c502.jpg" />
<img src="https://s.yimg.com/uu/api/res/1.2/TVnjyBmzZWNlxeO5CvVkfQ--~B/aD0xMjAwO3c9MTIwMDthcHBpZD15dGFjaHlvbg--/https://media.zenfs.com/en/e__181/b609e20726211710ba3bef9a8dba183d" />
<img src="https://wallpapercave.com/wp/wp4434081.jpg" />
<img src="https://celebsuburb.com/wp-content/uploads/2024/09/obi-ndefo-death-1.jpg" />
</div>
</div>