简体   繁体   中英

JavaScript Change Background Color On Scroll

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>

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>

I see 2 solutions:

  1. You only add classes to your body, so with time body will have every class and its color will be set to last class added, so you should also remove each unused class with classList.remove('className') ;
  2. Just change body background with document.body.style.background = '#FFFFFF' , and add comments for each color changed to avoid confusion.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM