Sunday, May 19, 2024
 Popular · Latest · Hot · Upcoming
171
rated 0 times [  175] [ 4]  / answers: 1 / hits: 25276  / 6 Years ago, wed, february 7, 2018, 12:00:00

I have a div that I want to change color when it scrolls into the viewport, and I'm trying to achieve this with the new intersectionObserver method. I've set my parameters in the config callback, but I can't seem to get the observer itself to add the class to change the background color?



Any help would be amazing.



codepen: https://codepen.io/emilychews/pen/mXVBVK





const config = {
root: null, // sets the framing element to the viewport
rootMargin: '0px',
threshold: 0.5
};

const box = document.getElementById('box');

let observer = new IntersectionObserver(function(entries) {
observer.observe(box);
entries.forEach(function(item){
item.classList.add(active);
});
}, config);

body {
margin: 0; padding: 0;
display:flex;
justify-content: center;
align-items: center;
height: 300vh;
}

#box {
width: 100px;
height: 100px;
background: blue;}

.active {background: red;}

<div id=box></div>




More From » html

 Answers
22

The function inside the IntersectionObserver constructor is called whenever an intersection changes. You can’t put observer.observe(box); inside it.


Also, item isn’t a DOM element — it’s an IntersectionObserverEntry, so you can’t use .classList on it. You probably meant to address item.target.


Even if the above is corrected, your CSS won’t change, because you’ve used the #box selector to set the background to blue, which has a higher specificity than .active. An easy fix is to change #box to .box and as HTML use <div id="box" class="box"></div> instead.


The corrected code would then look like this:




const config = {
root: null, // Sets the framing element to the viewport
rootMargin: 0px,
threshold: 0.5
},
box = document.getElementById(box),
observer = new IntersectionObserver((entries) => entries
.forEach(({ target: { classList } }) => classList.add(active)), config);

observer.observe(box);

body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 300vh;
}
.box {
width: 100px;
height: 100px;
background: blue;
}
.active {
background: red;
}

<div id=box class=box></div>




Now you need some logic inside the callback:


entries.forEach(({ target: { classList }, intersectionRatio }) => {
if(intersectionRatio >= 0.5){
classList.add("active");
}
else{
classList.remove("active");
}
});

This will make the <div> red when 50 % or more of it is visible. The observer will stop firing after 50 % or more is visible, so in some cases intersectionRatio will be exactly 0.5.




const config = {
root: null, // Sets the framing element to the viewport
rootMargin: 0px,
threshold: 0.5
},
box = document.getElementById(box),
observer = new IntersectionObserver((entries) => entries
.forEach(({ target: { classList }, intersectionRatio }) => {
if(intersectionRatio >= 0.5){
classList.add(active);
}
else{
classList.remove(active);
}
}), config);

observer.observe(box);

body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 300vh;
}
.box {
width: 100px;
height: 100px;
background: blue;
}
.active {
background: red;
}

<div id=box class=box></div>




[#55227] Monday, February 5, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
destanyb

Total Points: 407
Total Questions: 88
Total Answers: 88

Location: Senegal
Member since Mon, Sep 5, 2022
2 Years ago
;