1

so I made an attempt at writing my own version of code to change the background color of a page on scroll. I've searched all over the internet, but I just keep finding Jquery examples and no vanilla JS ones that really show me exactly how to do it.

My first thoughts were to handle the colors and animation in css and trigger them in JS. If I would like to handle animations in CSS, this is the way to go, no? Anyway, my code is obviously not working, so would anyone be able to help me out?

It's probably not as efficient as it should be, so any tips there would be helpful as well.

I haven't finished the animation part yet in css, but the groundwork is laid out. So my idea was to select all of the different colors, then put them into an array. Then make a for loop inside of the function.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="css\style.css">
    <title>Site experiment</title>
</head>
<body>

<section>
<h1 id="first-h1">This site is an experiment on scroll effects</h1>
</section>

<section>
<h1 id="second-h1">I really hope this helps me learn vanilla JavaScript better</h1>
</section>

<section>
<h1 id="third-h1">I think it will honestly</h1>
</section>

<section>
<h1 id="fourth-h1">Or maybe it will frustrate me till the end of time</h1>
</section>

<section>
<h1 id="fifth-h1">Even if that does happen, I'll still keep trying</h1>
</section>

</body>
<script src="js\app.js"></script>
</html>

@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Roboto Mono', monospace;
}

body {
    background-color: #E5E1EE;
    transition: 0.3s all;
}

section {
    height: 100vh;
}

h1 {
    margin: 15rem;
}

.lightCyan {
    background-color: #DFFDFF;
}

.darkSkyBlue {
    background-color: #90BEDE;
}

.aquamarine {
    background-color: #68EDC6;
}

.electricBlue {
    background-color: #90F3FF;
}

    let bdy = document.querySelector('body');
let cyan = bdy.classList.add('lightCyan');
let skyBlue = bdy.classList.add('darkSkyBlue');
let aqua = bdy.classList.add('aquamarine');
let electric = bdy.classList.add('electricBlue');
let colors = [cyan, skyBlue, aqua, electric];


window.addEventListener('scroll', function () {
    if (document.documentElement.scrollTop || document.body.scrollTop > window.innerHeight) {
        for(let i = 0; i < colors.length; i++) {
           colors.push(i);
        }
    }
})
eddiepearson
  • 31
  • 1
  • 7

2 Answers2

3

If you want to change the background color when a given section hits the top of the screen, you could try something like:

const colors = ['', 'lightCyan', 'darkSkyBlue', 'aquamarine', 'electricBlue']

const sections = [...document.getElementsByTagName('section')]

window.addEventListener('scroll', function () {

  const scrollFromTop = window.pageYOffset

  for (let i = 0; sections.length > i; i++) {

    if (scrollFromTop <= sections[i].offsetTop) {
      document.body.className = colors[i] 
      break
    } 

  }

})
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Roboto Mono', monospace;
}

body {
  background-color: #E5E1EE;
  transition: 0.3s all;
}

section {
  height: 100vh;
}

h1 {
  margin: 15rem;
}

.lightCyan {
  background-color: #DFFDFF;
}

.darkSkyBlue {
  background-color: #90BEDE;
}

.aquamarine {
  background-color: #68EDC6;
}

.electricBlue {
  background-color: #90F3FF;
}
<section>
<h1 id="first-h1">This site is an experiment on scroll effects</h1>
</section>

<section>
<h1 id="second-h1">I really hope this helps me learn vanilla JavaScript better</h1>
</section>

<section>
<h1 id="third-h1">I think it will honestly</h1>
</section>

<section>
<h1 id="fourth-h1">Or maybe it will frustrate me till the end of time</h1>
</section>

<section>
<h1 id="fifth-h1">Even if that does happen, I'll still keep trying</h1>
</section>
  • So I tried exactly this and it stops working after the first color change. Also, would this make it work when scrolling from bottom to top? – eddiepearson May 21 '19 at 14:41
  • @eddiepearson I have added the CSS and the HTML, so you can run the code here, it does work in either direction. –  May 21 '19 at 19:38
  • ahh thank you so much! This is fantastic. What does the "break" do? Is that some built in function? – eddiepearson May 24 '19 at 12:21
  • also, what does the "..." do in the section array? "...document" etc. Could I just use a "querySelectorAll"? – eddiepearson May 24 '19 at 12:25
  • @eddiepearson The `break` statement terminates the current loop. You can read about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break What it does here, is terminating the loop once the program finds the first section that hasn't reached the top of the screen. See what happens, if you leave out the break: it loops all the way through, so we always end up with the last color. –  May 24 '19 at 13:19
  • @eddiepearson The `...` is the spread operator, and what it does here, is convert a HTMLCollection to an array. You can learn more about spread here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax And here is a discussion about converting a HTMLCollection to an array: https://stackoverflow.com/questions/222841/most-efficient-way-to-convert-an-htmlcollection-to-an-array –  May 24 '19 at 13:27
  • @eddiepearson And yes, you could use `querySelectorAll` instead of `getElementsByTagName`, and you probably should: the `section` element is too general, so you would want to give these sections a class, and select that class with `querySelectorAll`. –  May 24 '19 at 13:37
0

You can just use a trivial array of colors.

let bdy = document.querySelector('body');
let colors = ['lightgreen', 'tomato', 'orange', 'purple'];

window.addEventListener('scroll', function () {
    if (document.documentElement.scrollTop || window.pageYOffset > window.innerHeight) {
    var diff = parseInt(window.pageYOffset - window.innerHeight);
    var step = parseInt(window.innerHeight*2);
    bdy.style.backgroundColor = colors[Math.floor(diff/step)];
    }
})
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Roboto Mono', monospace;
}

body {
    background-color: #E5E1EE;
    transition: 0.3s all;
}

section {
    height: 100vh;
}

h1 {
    margin: 15rem;
}

.lightCyan {
    background-color: #DFFDFF;
}

.darkSkyBlue {
    background-color: #90BEDE;
}

.aquamarine {
    background-color: #68EDC6;
}

.electricBlue {
    background-color: #90F3FF;
}
<section>
<h1 id="first-h1">This site is an experiment on scroll effects</h1>
</section>

<section>
<h1 id="second-h1">I really hope this helps me learn vanilla JavaScript better</h1>
</section>

<section>
<h1 id="third-h1">I think it will honestly</h1>
</section>

<section>
<h1 id="fourth-h1">Or maybe it will frustrate me till the end of time</h1>
</section>

<section>
<h1 id="fifth-h1">Even if that does happen, I'll still keep trying</h1>
</section>
Banzay
  • 9,310
  • 2
  • 27
  • 46
  • Hello. Why did you put an if statement ? When you are at the top on the window, both conditions are false. Moreover, your solution does not adapt with the viewport height. Try it with a larger height. – mootookoi Jul 15 '19 at 15:58
  • @mootookoi If both conditions are false, then bg-color doesn't change - I followed this logic. I didn't try adapting to height, cause it's not a place to make somebody's work. I just gave a direction on how to solve the issue – Banzay Jul 15 '19 at 16:48