Hi.
I'm wondering, what are the best practices for making the page below responsive, even only for desktop screens (width > 1024px)? Currently, it works perfectly for 1920x919 browser screens. It uses Scroll Trigger for parallax scrolling with various images as layers. Any deviance of screen width and height has a huge impact on how the page looks. I realize that having different images of different sizes is one way to improve this perhaps, but what about vertical scrolling?
Thank you.
/* eslint-disable @next/next/no-img-element */
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import Head from "next/head";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { useShopifyData } from "@/hooks";
import { FloatingMenu, FooterProduct } from "@/components";
export default function Verdelore() {
const { shopifyPages } = useShopifyData();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [windowHeight, setWindowHeight] = useState(0);
const fullBgRef = useRef(null);
const scrollerRef = useRef(null);
const firstSectionRef = useRef(null);
const secondSectionRef = useRef(null);
const thirdSectionRef = useRef(null);
const ffithSectionRef = useRef(null);
const footerRef = useRef(null);
const bgLeftRef = useRef(null);
const bgRightRef = useRef(null);
const bgFooterRef = useRef(null);
const elfRef = useRef(null);
const canRef = useRef(null);
const magicPotionTextRef = useRef(null);
const elixirTextRef = useRef(null);
const speed = windowHeight / 3.08;
useLayoutEffect(() => {
let ctx = gsap.context(() => {
gsap.registerPlugin(ScrollTrigger);
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".scrollElement",
start: "top top",
end: 12000,
scrub: 5,
invalidateOnRefresh: true,
},
});
// Scroll past first title section
tl.to(fullBgRef.current, { y: -1.5 * speed, duration: 1.5 }, 0);
tl.to(firstSectionRef.current, { y: -2.5 * speed, opacity: 0, duration: 1.5 }, 0);
// Scroll to second section
tl.fromTo(
bgLeftRef.current,
{ y: 0, opacity: 0.9, x: -5 * speed, ease: "power1.out" },
{ y: -3.1 * speed, opacity: 1, x: 0, duration: 2 },
0.08,
);
tl.fromTo(
bgRightRef.current,
{ y: 0, opacity: 0.9, x: 5 * speed, ease: "power1.out" },
{ y: -3 * speed, opacity: 1, x: 0, duration: 2 },
0.08,
);
tl.to(secondSectionRef.current, { y: -2.7 * speed, duration: 2 }, 0.06);
// Move slide 2 up
tl.to(secondSectionRef.current, { y: -8 * speed, duration: 1.8 }, "+=0.5");
// Scroll to third section
tl.to(fullBgRef.current, { y: -4 * speed, duration: 1.5 }, "<");
tl.to(bgLeftRef.current, { y: -5.8 * speed, duration: 2 }, "<");
tl.to(bgRightRef.current, { y: -8.25 * speed, duration: 2.7 }, "<");
tl.to(thirdSectionRef.current, { y: -5.25 * speed, duration: 1.8, delay: 0.8 }, "<");
// Scroll to fourth section
tl.to(bgRightRef.current, { y: -9.8 * speed, duration: 2 }, "+=0.5");
tl.to(bgLeftRef.current, { y: -7 * speed, duration: 2 }, "<");
tl.to(fullBgRef.current, { y: -4.6 * speed, duration: 2 }, "<");
tl.to(thirdSectionRef.current, { y: -8 * speed, duration: 2 }, "<");
tl.to(bgFooterRef.current, { y: -7.3 * speed, duration: 2.5 }, "<");
tl.fromTo(
elfRef.current,
{ y: 0, opacity: 0.3, x: 0, width: 250, duration: 2.5, ease: "power1.out" },
{ y: -9.2 * speed, opacity: 1, x: 1.1 * speed, width: "21vw", duration: 3, scale: 1 },
"<",
);
tl.to(elfRef.current, { x: 4 * speed, opacity: 0, duration: 2.25 }, "+=0.7");
// Scroll to fifth section
tl.fromTo(elixirTextRef.current, { x: 0, opacity: 0 }, { y: -9 * speed, opacity: 0 }, "<");
tl.fromTo(
magicPotionTextRef.current,
{ x: 0, opacity: 0 },
{ y: -9 * speed, opacity: 0 },
"<",
);
tl.to(canRef.current, { y: -9 * speed, opacity: 0 }, "<");
tl.to(bgFooterRef.current, { y: -10.5 * speed, duration: 2 }, "-=1.3");
tl.to(elixirTextRef.current, { x: 0.7 * speed, opacity: 1, duration: 2.5 }, "-=1.1");
tl.to(
magicPotionTextRef.current,
{ x: 0.7 * speed, opacity: 1, duration: 2.5, delay: 0.2 },
"<",
);
tl.fromTo(
canRef.current,
{ x: 1 * speed, opacity: 0, width: "100px" },
{ width: "13vw", opacity: 1, duration: 2.5 },
"<",
);
// Scroll to footer
tl.to(ffithSectionRef.current, { y: -14 * speed, duration: 5 }, "+=0.5");
tl.to(bgFooterRef.current, { y: -14 * speed, duration: 3 }, "<");
tl.to(footerRef.current, { y: -11.5 * speed, duration: 3 }, "-=5.75");
});
return () => {
ctx.revert();
};
}, [speed]);
useEffect(() => {
const handleResize = () => {
setWindowHeight(window.innerHeight);
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return (
<>
<Head>
<title>Verdelore | Elven Springs</title>
<meta name="description" content="Verdelore" />
</Head>
<div className="wrapper relative z-40 h-[205vh] overflow-hidden bg-bg">
<main className="content" ref={scrollerRef}>
<img
src="/assets/images/center.png"
alt="bg"
className="bg absolute w-full"
ref={fullBgRef}
/>
<section
className="relative z-50 flex h-screen flex-col items-center justify-center"
ref={firstSectionRef}
>
<FloatingMenu isMenuOpen={isMenuOpen} setIsMenuOpen={setIsMenuOpen} />
<div>
<img src="/assets/images/logo.png" alt="logo" className="h-fit w-[500px]" />
</div>
</section>
<img
src="/assets/images/bg-left.png"
alt="bg"
className="absolute left-0 w-[25vw]"
ref={bgLeftRef}
/>
<img
src="/assets/images/bg-right-full.png"
alt="bg"
className="absolute right-0 w-[100vw]"
ref={bgRightRef}
/>
<section
className="relative z-20 flex h-screen flex-col items-center text-center"
ref={secondSectionRef}
>
<h1 className="mb-6 font-heading text-[3.6vw] text-secondary">
{shopifyPages?.verdelore?.title}
</h1>
<p
className="max-w-lg font-dunbar text-[1.33vw] font-medium leading-[1.33] xl:max-w-xl 2xl:max-w-3xl"
dangerouslySetInnerHTML={{ __html: shopifyPages?.verdelore?.body as TrustedHTML }}
/>
</section>
<section
className="relative z-10 flex h-screen flex-col items-center text-center"
ref={thirdSectionRef}
>
<h2 className="mb-6 font-heading text-[3.6vw] text-black">
{shopifyPages?.forasdal?.title}
</h2>
<p
className="max-w-lg font-dunbar text-[1.33vw] font-medium leading-[1.33] xl:max-w-xl 2xl:max-w-3xl"
dangerouslySetInnerHTML={{ __html: shopifyPages?.forasdal?.body as TrustedHTML }}
/>
</section>
<img src="/assets/images/elf.png" alt="bg" className="absolute left-0" ref={elfRef} />
<img
src="/assets/images/bg-footer.png"
alt="bg"
className="absolute left-0 w-full"
ref={bgFooterRef}
/>
<section className="relative z-10 flex h-screen" ref={ffithSectionRef}>
<div className="max-w-[40vw] space-y-10 pt-5">
<div className="space-y-4" ref={magicPotionTextRef}>
<h2 className="pl-[36px] font-heading text-[2.1vw] uppercase leading-[104px] text-aqua">
{shopifyPages?.["magic-potion"]?.title}
</h2>
<p
className="font-dunbar text-[1.15vw] text-aqua"
dangerouslySetInnerHTML={{
__html: shopifyPages?.["magic-potion"]?.body as TrustedHTML,
}}
/>
</div>
<div className="space-y-10" ref={elixirTextRef}>
<div className="space-y-4">
<h2 className="pl-[36px] font-heading text-[2.1vw] uppercase leading-[104px] text-aqua">
{shopifyPages?.elexir?.title}
</h2>
<p
className="font-dunbar text-[1.15vw] text-aqua"
dangerouslySetInnerHTML={{
__html: shopifyPages?.elexir?.body as TrustedHTML,
}}
/>
</div>
<a
href="https://elvensprings.myshopify.com/products/elven-spring-water-19-2-oz-king-size-cans-12-pack"
className="ml-[36px] block w-fit rounded-full border-3 border-green bg-white bg-opacity-30 px-7 py-2 font-dunbar text-xs font-bold uppercase text-green transition hover:bg-opacity-0 sm:mt-4 sm:text-sm xl:px-16 xl:py-2 xl:text-lg 2xl:px-20 2xl:py-4 2xl:text-xl"
target="_blank"
rel="noreferrer"
>
Pre-order
</a>
</div>
</div>
<img
src="/assets/images/verdelore-can.png"
alt="bg"
className="h-fit w-full"
ref={canRef}
/>
</section>
<section className="absolute w-full" ref={footerRef}>
<FooterProduct />
</section>
</main>
</div>
<div className="scrollElement" />
</>
);
}