Reputation: 3423
I am practicing Javascript and css. I want to change my background color when scrolling down. I don't want to use library for that. I have followed this code-pen demo to learn the logic but he used jquery. I have followed w3school for scrollTop .My javascript logic works but it does not work like this demo. I think I have to target each div
in order to change the background-color but don't know how.
function showScrollColorChange() {
//let scroll = window.scrollTop() + (window.height() / 3);
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 30) {
document.body.classList.add('color-violet')
} if (document.body.scrollTop > 40 || document.documentElement.scrollTop > 40) {
document.body.classList.add('color-green')
} else {
document.body.classList.add('color-orange')
}
}
/* document.body.addEventListener('scroll', () => {
showScrollColorChange()
}) */
window.onscroll = function () { showScrollColorChange() };
*{
box-sizing: border-box;
}
body{
margin: 0;
padding: 0;
transition: background 300ms linear, color 300ms linear;
}
.container{
display: flex;
justify-content: center;
margin-top: 20px;
padding: 50px;
min-height: 100vh;
}
p{
width:50%;
font-size: 20px;
}
img {
width:500px;
height: 500px;
border-radius: 5px;
}
/* colours */
.color-violet {
background-color: #7A4EAB;
}
.color-indigo {
background-color: #4332CF;
}
.color-blue {
background-color: #2F8FED;
}
.color-green {
background-color: #4DCF42;
}
.color-yellow {
background-color: #FAEB33;
}
.color-orange {
background-color: #F19031;
}
.color-red {
background-color: #F2293A;
}
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
Upvotes: 0
Views: 729
Reputation: 317
Here is a dynamic way.
Get all containers elements and add the position of their top to an array:
containers = document.getElementsByClassName("container");
var containertops = [];
containertops.push(0); // add for space before 1st container
for (var i = 0; i < containers.length; i++) {
containertops.push(containers[i].offsetTop);
}
Make an array of the colour classes in the order to be used. It is easy to change the colours and order doing this:
// array of colours to use
var colours = [
"white",
"color-violet",
"color-indigo",
"color-blue",
"color-green",
"color-yellow",
"color-orange",
"color-red",
];
In scroll function, loop through the array of containers top positions. For each i
in the loop, use this as an index to get a new colour from the colours array so the colour changes for every container. If there are more containers than colours, use the last colour for the rest.
// loop through the containers and add a new colour as the containers change
for (var i = 0; i < containertops.length; i++) {
// if this container is at the top of the screen get a new colour class
if (document.body.scrollTop >= containertops[i] || document.documentElement.scrollTop >= containertops[i]) {
document.body.className = ''; // clear class
// if we have not enough colours, use the last colour class again
colourclass= (i>=colours.length?colours.length-1: i);
document.body.classList.add(colours[colourclass]);
}
}
This is the code working:
//dynamically add all containers to array
containers = document.getElementsByClassName("container");
var containertops = [];
containertops.push(0); // add for space before 1st container
for (var i = 0; i < containers.length; i++) {
containertops.push(containers[i].offsetTop);
}
// array of colours to use
var colours = [
"white",
"color-violet",
"color-indigo",
"color-blue",
"color-green",
"color-yellow",
"color-orange",
"color-red",
];
function showScrollColorChange() {
// loop through the containers and add a new colour as the containers change
for (var i = 0; i < containertops.length; i++) {
// if this container is at the top of the screen get a new colour class
if (document.body.scrollTop >= containertops[i] || document.documentElement.scrollTop >= containertops[i]) {
document.body.className = ''; // clear class
// if we have not enough colours, use the last colour class again
colourclass= (i>=colours.length?colours.length-1: i);
document.body.classList.add(colours[colourclass]);
}
}
}
window.onscroll = function() {
showScrollColorChange()
};
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
transition: background 300ms linear, color 300ms linear;
}
.container {
display: flex;
justify-content: center;
margin-top: 20px;
padding: 50px;
min-height: 100vh;
}
p {
width: 50%;
font-size: 20px;
}
img {
width: 500px;
height: 500px;
border-radius: 5px;
}
/* colours */
.color-violet {
background-color: #7A4EAB;
}
.color-indigo {
background-color: #4332CF;
}
.color-blue {
background-color: #2F8FED;
}
.color-green {
background-color: #4DCF42;
}
.color-yellow {
background-color: #FAEB33;
}
.color-orange {
background-color: #F19031;
}
.color-red {
background-color: #F2293A;
}
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
Upvotes: 1
Reputation: 14904
IntersectionObserver
comes here very handy. You just observer every container.
I have put an custom attribute called _class
to the element. It holds the name of the class that should be added / removed if the elemen enters / leaves the viewport.
The observer runs off the main thread so its more performant.
To see how it works you need to turn on fullscreen. The threshold is set to 0.9 witch means 90% of the div needs to be visible before the class will be added to the body.
let containers = document.querySelectorAll(".container")
let observer = new IntersectionObserver((entries) => {
entries.forEach((entry, i) => {
let color = entry.target.attributes._class.nodeValue;
if(entry.isIntersecting) {
document.body.className = "";
document.body.classList.add(color);
}
})
}, {threshold: 0.9})
containers.forEach(container => {
observer.observe(container);
})
*{
box-sizing: border-box;
padding: 0;
margin: 0;
}
body{
margin: 0;
padding: 0;
transition: background 300ms linear, color 300ms linear;
}
.container{
display: flex;
justify-content: center;
margin-top: 20px;
padding: 50px;
min-height: 100vh;
}
p{
width:50%;
font-size: 20px;
}
img {
width:500px;
height: 500px;
border-radius: 5px;
}
/* colours */
.color-violet {
background-color: #7A4EAB;
}
.color-indigo {
background-color: #4332CF;
}
.color-blue {
background-color: #2F8FED;
}
.color-green {
background-color: #4DCF42;
}
.color-yellow {
background-color: #FAEB33;
}
.color-orange {
background-color: #F19031;
}
.color-red {
background-color: #F2293A;
}
<div _class="color-violet" class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div _class="color-indigo" class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div _class="color-blue" class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div _class="color-green" class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
<div _class="color-yellow" class="container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil at eaque in aliquam assumenda. Officiis omnis ex
sunt quaerat magni. Provident at nihil molestias dolores tempora voluptas laborum aspernatur sint.</p>
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
Upvotes: 0
Reputation: 1
I see 2 solutions:
classList.remove('className')
;document.body.style.background = '#FFFFFF'
, and add comments for each color changed to avoid confusion.Upvotes: 0