skip to Main Content

I’m trying to make a webpage where a div element changes its background color as the user scrolls down the page. I want the color to transition smoothly between different shades as the scroll progresses. I’ve tried using window.onscroll, but I’m struggling to get the right values to make the color change look smooth. Could anyone show me how to achieve this effect using vanilla JavaScript? Thanks in advance!

I attempted using window.onscroll to detect the scroll position and then change the backgroundColor of the div. I tried calculating a color value based on window.scrollY but found the colors were changing too abruptly. Here’s a snippet of what I’ve got so far:

window.onscroll = () => {
  const scrollPos = window.scrollY;
  const colorValue = Math.min(255, scrollPos / 5);  // Attempt to scale color with scroll
  document.getElementById('myDiv').style.backgroundColor = `rgb(${colorValue}, 100, 150)`;
};

What I Expected:
"I was hoping for a smooth transition where the background color would gradually change as I scroll down the page. Right now, it’s either changing too quickly or jumping to values I didn’t intend. I’m also open to using different color transitions if there’s a better approach to achieve a fluid, natural effect."

4

Answers


  1. As written, the colorValue will have 255 / 5 steps, no matter how may steps are in the window, so the entire color effect will occur in the first 51 lines.

    You might try setting the colorValue to a percentage of the scroll position compared to the full length and see if that’s more to your liking.

    window.onscroll = () => { 
      const scrollPos = window.scrollY;
      const colorValue = Math.min(255, (scrollPos * 100) / window.innerHeight)
      const myDiv = document.getElementById('myDiv');
      myDiv.style.backgroundColor = `rgb(${colorValue}, 100, 150)`;
    };
    
    Login or Signup to reply.
  2. This version runs on all 3 of RGB so it is extra smooth

    const myDiv = document.getElementById('myDiv');
    window.onscroll = () => {
      const scrollPos = window.scrollY;
      const maxScroll = document.body.scrollHeight - window.innerHeight;
    
      // Calculate the scroll (0 to 1)
      const scrollPercent = Math.min(scrollPos / maxScroll, 1);
    
      // Define your own start and end colors for the gradient (in RGB format)
      const startColor = { r: 100, g: 150, b: 200 }; // Light blue
      const endColor   = { r: 255, g: 100, b: 150 }; // Light pink
    
      // Interpolate based on the scroll percentage
      const r = Math.round(startColor.r + (endColor.r - startColor.r) * scrollPercent);
      const g = Math.round(startColor.g + (endColor.g - startColor.g) * scrollPercent);
      const b = Math.round(startColor.b + (endColor.b - startColor.b) * scrollPercent);
    
      myDiv.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
    };
    #myDiv {
      height: 5000px;
    }
    <div id="myDiv">Start scrolling</div>
    Login or Signup to reply.
  3. If you use the ratio of the scrollable area to the content, you will get a smooth transition from 0 to 255.

    In this snippet you can see that gradual change in the color changing and the console output of the color value.

    window.onscroll = () => {
      const colorValue = 255 * (window.scrollY / (document.body.scrollHeight - window.innerHeight))
      document.getElementById('myDiv').style.backgroundColor = `rgb(${colorValue}, 100, 150)`;
    
      console.log( Math.floor(colorValue) )
    };
    #myDiv {
      position: fixed;
      top: 0;
      left: 0;
      width:  200px;
      height: 100px;
      border: solid 2px blue;
      box-shadow: 2px 2px 4px black;
    }
    
    .Huge {
      font-size: 4rem;
      height: 400px;
    }
    <div id="myDiv">
      Hello there!
    </div>
    
    <div class="Huge">Start</div>
    <div class="Huge">1</div>
    <div class="Huge">2</div>
    <div class="Huge">3</div>
    <div class="Huge">4</div>
    <div class="Huge">Bye bye</div>
    Login or Signup to reply.
  4. Map the scroll position to a range of color values.

    window.onscroll = () => {
      const progress = window.scrollY / (document.body.scrollHeight - window.innerHeight);
      const [r, g, b] = [255, 100, 150].map((start, i) => Math.round(start + (100 - start) * progress));
      document.getElementById('myDiv').style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search