Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically change background color on scroll

Is there any way to change background color dynamically on scroll?

For example, refer this site(https://www.samsung.com/sec/smartphones/galaxy-note9/)

When you first access that site, background color is blue.

While scroll down, it's color change to black smoothly.

Also see this site(codepen.io/Funsella/pen/yLfAG/)

Second site is same with first. But it's color changed at once.

But first site's color is not change at once.

It changed gradually related to scroll position.

body {
  height: 100vh;
}
.section1 {
  background-color: white;
  height: 100%;
}
.section2 {
  background: linear-gradient(#f05fa6, #ed1654);
  height: 100%;
}
<html>
<body>
  <section class="section1">
    SECTION1
  </section>
  <section class="section2">
    SECTION2
  </section>
</body>
</html>

Above code is what I'm worked on.

Current it's color is split by each section.

When I scroll down, I want to change color background-color: white -> background: linear-gradient(#f05fa6, #ed1654)

Is there any solution about this?

like image 558
Hide Avatar asked Oct 04 '18 01:10

Hide


2 Answers

You need to smoothly interpolate the colors by taking into account the page's scroll offset (window.scrollY, or window.pageYOffset on older browsers).

The Samsung site is transitioning a solid color instead of a gradient, which is a bit simpler.

Like this (see CodePen):

const [red, green, blue] = [69, 111, 225]
const section1 = document.querySelector('.section1')

window.addEventListener('scroll', () => {
  let y = 1 + (window.scrollY || window.pageYOffset) / 150
  y = y < 1 ? 1 : y // ensure y is always >= 1 (due to Safari's elastic scroll)
  const [r, g, b] = [red/y, green/y, blue/y].map(Math.round)
  section1.style.backgroundColor = `rgb(${r}, ${g}, ${b})`
})

You can apply the same logic to the gradient colors.

like image 57
atomiks Avatar answered Oct 19 '22 23:10

atomiks


I tried to use the solution of atomiks with a custom end color but it was too difficult. I found myself a better solution by using chroma.js

You need to generate a scale with your two colors (or more) :

var scale = chroma.scale(['#1abc9c', '#e74c3c']).domain([0, $(document).height()]);
$(window).on('scroll', function () {
    $('.section').css('background-color', scale(window.pageYOffset));
});

Here I create a scale with the color I want and then I add a custom domain so that my scale can use the offset position which can go from 0 (top of the page) 3600 (bottom of my page). Or, you can try to get the scroll position value between 0 and 1 with some math.

Then, when we scroll, we can use our scale with the current scroll position. It will generate a RGBA color between our two colors before reaching the last one at the bottom of the page #e74c3c

like image 43
Baptiste Avatar answered Oct 20 '22 01:10

Baptiste