Live Demo / Download
Scroll animations appear to be a rising pattern currently, particularly for landing pages for SaaS and modern tech startups. These animations are conceived to beautify the person expertise, so long as they’re properly coded and never too intrusive for the ultimate person. We have beforehand created tutorials on this matter, just like the card waterfall animation on scroll or the gradient text reveal. At this time we’ll be including one other instance to the checklist: altering the background coloration of a web page as you scroll. This impact will will let you add dynamism to your design and make each part distinctive.
Structuring the HTML
On this demo, we are going to create a <principal>
factor with 4 sections, every related to a special coloration from the Tailwind palette: Sky 200, Purple 200, Pink 200, and Emerald 200. To make sure clean coloration transitions, we cannot straight apply background colours to particular person sections. As a substitute, we’ll use the Intersection Observer API to find out which part is dominant and apply the corresponding background coloration to the principle container. This is the fundamental HTML construction:
<principal class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden">
<div class="w-full max-w-5xl mx-auto px-4 md:px-6">
<div class="pt-6 pb-12 md:pt-10 md:pb-20">
<!-- Sky part -->
<part>
<!-- ... content material ... -->
</part>
<!-- Purple part -->
<part>
<!-- ... content material ... -->
</part>
<!-- Pink part -->
<part>
<!-- ... content material ... -->
</part>
<!-- Emerald part -->
<part>
<!-- ... content material ... -->
</part>
</div>
</div>
</principal>
We have set the default background coloration of the <principal>
factor to Sky 200 (bg-sky-200
, which is the colour of the primary part) and ensured it fills no less than the peak of the viewport utilizing min-h-screen
.
Making a JS class
Let’s create a file bg-scroll.js
within the challenge’s root, and embrace it in our HTML doc:
<script src="./bg-scroll.js"></script>
In that file, we’ll outline a category named BgScroll
exposing a init
methodology for initializing the observer. This is the code to start out:
class BgScroll {
constructor(factor) {
this.factor = factor;
this.init();
}
init() {
}
}
// Init BgScroll
const el = doc.querySelector('[data-bg-scroll]');
new BgScroll(el);
On the finish of the file, we specify how you can initialize the category by including a data-bg-scroll
attribute to the <principal>
factor within the HTML:
<principal class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden" data-bg-scroll>
Creating the observer
Now, we’ll write the code to initialize the observer:
class BgScroll {
constructor(factor) {
this.factor = factor;
this.sections = this.factor.querySelectorAll('part');
this.observeSection = this.observeSection.bind(this);
this.init();
}
observeSection(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log(entry.goal);
}
});
}
init() {
const observer = new IntersectionObserver(this.observeSection, { rootMargin: '-50% 0% -50% 0%' });
this.sections.forEach(part => {
observer.observe(part);
});
}
}
// Init BgScroll
const el = doc.querySelector('[data-bg-scroll]');
new BgScroll(el);
We have now created a brand new occasion within the constructor, known as sections
, which comprises an array of all of the sections inside the principle factor. Within the init()
methodology, we loop by way of this array and create a brand new observer for every part. The primary argument of the IntersectionObserver
is the callback that will likely be executed each time a bit enters or exits the viewport (i.e., observeSection
). The second argument is an choices object, which comprises the rootMargin
property. Through the use of the values -50% 0% -50% 0%
, we’re telling the IntersectionObserver
to set off the callback when the part intersects an imaginary horizontal line positioned 50% from the highest of the viewport. For testing functions, we have added a console.log
contained in the observeSection
methodology to determine the dominant part as you scroll.
Altering the background coloration
Now that we all know which is the dominant part, we will apply the corresponding background coloration to the <principal>
factor. To do that, we’ll outline the background coloration of every part utilizing a data-bg-color
attribute and the Tailwind class of the corresponding background coloration:
<principal class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden" data-bg-scroll>
<div class="w-full max-w-5xl mx-auto px-4 md:px-6">
<div class="pt-6 pb-12 md:pt-10 md:pb-20">
<!-- Sky part -->
<part data-bg-class="bg-sky-200">
<!-- ... content material .... -->
</part>
<!-- Purple part -->
<part data-bg-class="bg-purple-200">
<!-- ... content material .... -->
</part>
<!-- Pink part -->
<part data-bg-class="bg-pink-200">
<!-- ... content material .... -->
</part>
<!-- Emerald part -->
<part data-bg-class="bg-emerald-200">
<!-- ... content material .... -->
</part>
</div>
</div>
</principal>
Contained in the observeSection
methodology, we will now retrieve the attribute’s worth – which is entry.goal.dataset.bgClass
– and apply it to the principle factor:
class BgScroll {
constructor(factor) {
this.factor = factor;
this.sections = this.factor.querySelectorAll('part');
this.observeSection = this.observeSection.bind(this);
this.init();
}
observeSection(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Take away all bg courses
this.factor.classList.forEach(className => {
if (className.startsWith('bg-')) {
this.factor.classList.take away(className);
}
});
// Add the right bg class
this.factor.classList.add(entry.goal.dataset.bgClass);
}
});
}
init() {
const observer = new IntersectionObserver(this.observeSection, { rootMargin: '-50% 0% -50% 0%' });
this.sections.forEach(part => {
observer.observe(part);
});
}
}
// Init BgScroll
const el = doc.querySelector('[data-bg-scroll]');
new BgScroll(el);
And, as you could guess, we additionally take away all courses beginning with bg-
to make sure just one background class is utilized.
Including a fade animation
To finish our impact, we’ll add a fade animation to the background coloration change. Merely add the transition-colors
class to the <principal>
factor. The ultimate and easiest step is so as to add a fade animation to the background coloration change. To do that, simply add the transition-colors
class to the principle factor. Like this:
<principal class="relative min-h-screen flex flex-col bg-sky-200 transition-colors duration-700 overflow-hidden" data-bg-scroll>
We have now additionally added the duration-700
class to increase the animation length for a smoother impact.
Conclusions
Creating this dynamic background impact with the Intersection Observer is extremely straightforward. It takes simply round 30 strains of JavaScript, and no exterior libraries are required. Be at liberty to make your personal experiments and mess around with the code to match your particular wants. Do not forget to shoot us a message on Twitter if you happen to’ve already efficiently built-in the same impact into your website.