is there a way to change fixed element style when enter any section element on scroll
Solution 1:
The easiest thing to do would be to have the fixed button have a background color that looks good on all sections. That way you can just style it and leave it alone.
If you have to have the color change at different sections, there are a few ways of doing that, none are easy, and only a few would have good performance.
The best way of doing this that I can think of would be:
- Have the background of the
fixed
button be the default color. - Add a class modifier so that when you add one class it changes the style to the new color. Example:
.button
becomes.button.red
- On each section that has to change the background of the button, add a custom
data-attribute
Example:<section change-button-bg="red">
- Then
on load
- Set up a
.querySelectorAll(*[change-button-bg])
so that you can run a check on each of the sections. - Add a global variable called
currentTarget
- Set up an Intersection Observer on all the sections.
- Set up a
- Have the callback function for
.isIntersecting
do a few things.- Update the
currentTaget
variable - Update the color of the button
- Add a scroll listener
- Update the
- In the scroll listener watch the
bounds.bottom
ofcurrentTarget
to see which color it should be. - Then in the Intersection Observer, if it's no longer intersecting, remove the scroll listener to prevent memory leaks.
Here is a working example.
window.addEventListener('load', (event) => {
const changeBG = document.querySelectorAll('*[change-button-bg]');
let currentTarget = null;
const Observer = new IntersectionObserver((entries, Observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
currentTarget = entry.target;
addColor(true);
window.addEventListener('scroll', watchTarget);
} else {
addColor(false);
window.removeEventListener('scroll', watchTarget)
}
}
}, {threshold: 0.15});
for (const element of changeBG) {
Observer.observe(element);
}
function watchTarget() {
const bounds = currentTarget.getBoundingClientRect();
if (bounds.bottom < window.innerHeight - 80) {
addColor(false);
} else {
addColor(true);
}
}
function addColor(add) {
const btn = document.getElementById('button');
if (add) {
btn.classList.add('red');
} else {
btn.classList.remove('red');
}
}
});
body {
margin: 0;
}
section {
width: 100vw;
height: 100vh;
background: red;
}
section:nth-child(even) {
background: blue;
}
button {
position:fixed;
right: 50px;
bottom: 50px;
padding: 15px 25px;
border: none;
color: white;
background-color: blue;
cursor: pointer;
}
button.red {
background-color: red;
}
<html>
<body>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<button id="button">Top</button>
</body>
</html>
Solution 2:
this is the solution I was looking for I did it using Intersection Observer
document.addEventListener('DOMContentLoaded',()=>{
let options = {
root:null,
rootMargin:"-570px 0px -100px 0px",
threshold:0.05
};
let Observer= new IntersectionObserver(changColor,options);
document.querySelectorAll("section").forEach(section => {
Observer.observe(section);
});
});
function changColor(elements) {
elements.forEach(el => {
if (el.isIntersecting) {
let elbg=el.target.dataset.bg;
if (elbg=="blue") { //if section data-bg== blue
// change svg button style
document.getElementById("chatting_path_7").style.fill = "#fff";
document.getElementById("to_top_Ellipse_4").style.stroke = "#fff";
} else {
document.getElementById("chatting_path_7").style.fill = "#034ea2";
document.getElementById("to_top_Ellipse_4").style.stroke = "#034ea2";
}
}
})
}