April 8, 2026/Intermediate/Loaders & Intros

Full Orchestrated Load Sequence

A complete timed entrance sequence: loading screen holds for 2.5s, wipes away, then all page elements (headline, subtext, nav items) stagger in with coordinated timing via a GSAP timeline.

Digital experiences that move people.

We build motion-forward websites for studios, founders, and brands who want to stand out.

Loading
"use client";

import { useEffect, useRef, useState } from "react";
import gsap from "gsap";
import styles from "./styles.module.css";

export default function FullOrchestratedLoadSequence({ siteName = "", headline = "", subtext = "", navLinks = [] }) {
  const [isPlaying, setIsPlaying] = useState(false);
  const [isDone, setIsDone] = useState(false);
  const loaderRef = useRef(null);
  const navRef = useRef(null);
  const headlineRef = useRef(null);
  const subtextRef = useRef(null);

  function play() {
    if (isPlaying) return;
    setIsPlaying(true);
    setIsDone(false);

    // Reset all elements
    gsap.set(loaderRef.current, { yPercent: 0 });
    gsap.set(navRef.current?.children ?? [], { opacity: 0, y: 10 });
    gsap.set(headlineRef.current, { opacity: 0, y: 40 });
    gsap.set(subtextRef.current, { opacity: 0, y: 20 });

    const tl = gsap.timeline({
      onComplete: () => { setIsPlaying(false); setIsDone(true); },
    });

    // 1. Loading screen holds for 2.5s then wipes up
    tl.to(loaderRef.current, {
      yPercent: -100,
      duration: 0.8,
      ease: "power3.inOut",
      delay: 2.5,
    });

    // 2. Headline slides up
    tl.to(headlineRef.current, {
      opacity: 1,
      y: 0,
      duration: 0.8,
      ease: [0.16, 1, 0.3, 1],
    }, "-=0.3");

    // 3. Subtext fades in
    tl.to(subtextRef.current, {
      opacity: 1,
      y: 0,
      duration: 0.7,
      ease: [0.16, 1, 0.3, 1],
    }, "-=0.5");

    // 4. Nav items stagger in
    tl.to(navRef.current?.children ?? [], {
      opacity: 1,
      y: 0,
      stagger: 0.07,
      duration: 0.6,
      ease: [0.16, 1, 0.3, 1],
    }, "-=0.4");
  }

  return (
    <div className={styles.demo}>
      {/* Page content revealed after load */}
      <div className={styles.page}>
        <nav ref={navRef} className={styles.nav}>
          <span>{siteName}</span>
          {navLinks.map((link) => (
            <a key={link.label} href={link.href} className={styles.navLink}>
              {link.label}
            </a>
          ))}
        </nav>
        <div className={styles.hero}>
          <h1 ref={headlineRef} className={styles.headline}>{headline}</h1>
          <p ref={subtextRef} className={styles.subtext}>{subtext}</p>
        </div>
      </div>

      {/* Loading screen overlay */}
      <div ref={loaderRef} className={styles.loader}>
        <span className={styles.loaderText}>Loading</span>
      </div>

      {/* Controls */}
      {!isPlaying && (
        <button className={styles.playBtn} onClick={play}>
          {isDone ? "Replay" : "Play Sequence"}
        </button>
      )}
    </div>
  );
}
  • gsap

Related Components

3W AGO
Willem Loading Animationloaders
3MO AGO
Counter Loading Screenloaders