Tutorials
Malik Kotb
Feb 19, 2024 / Beginner / Short
A smooth color transition on scroll using JavaScript and TailwindCSS. Inspired by: https://backstagetalks.com/
Let's start the project by setting up a Next.js app with TypeScript and utilizing the app router. Just run npx create-next-app@latest
in the terminal.
We can clear out all the contents in the page.tsx, and global.css files, and add our own HTML and CSS, to begin with a clean slate in the application.
Create a components directory (next to the app directory) and create a new file Item.tsx
.
page.tsx
1"use client";
2import Image from "next/image";
3export default function Item({ source, index, isLast }) {
4 return (
5 <div className={`h-[${isLast ? 100 : 125}vh] items-center justify-center flex flex-col gap-2 m-0 p-0`}>
6 <div className="mt-[-10%]">
7 <Image src={source} alt={source} width={400} height={500} className="shadow-xl" />
8 <div className="flex flex-col p-4 mt-4 gap-2 text-center">
9 <p className="text-xl font-medium">Issue #{index + 1}</p>
10 <p className="text-lg font-medium text-white">GET HERE (Europe)</p>
11 <p className="text-sm font-medium">
12 or visit at <span className="text-white">selected museums</span>
13 </p>
14 </div>
15 </div>
16 </div>
17 );
18}
19
Where the magic happens..
You can define a list of image-paths and list of correspondong colors outside the JSX component. We will get the current scroll position and viewport height and then determine which section the user is currently in
page.tsx
1import { useEffect, useState } from "react";
2import Item from "./components/Item";
3export default function Home() {
4 const [backgroundColor, setBackgroundColor] = useState("#00c1b5");
5
6 useEffect(() => {
7 const changeBackgroundOnScroll = () => {
8 const scrollPosition = window.scrollY;
9 const viewportHeight = window.innerHeight;
10 const index = Math.floor(scrollPosition / viewportHeight);
11 setBackgroundColor(colors[index >= 4 ? 4 : index]);
12 };
13 window.addEventListener("scroll", changeBackgroundOnScroll);
14 return () => { window.removeEventListener("scroll", changeBackgroundOnScroll );
15 };
16 }, []);
17
18 return (
19 <section
20 style={{ backgroundColor: backgroundColor,
21 transition: "background-color 0.5s ease-out"}}>
22 {images.map((image, index) => (
23 <Item key={index} source={image}
24 index={index}
25 isLast={index === images.length - 1} />
26 ))}
27 </section>
28);
29}
30
background-color ease-out
for the smooth transition of the background color