SectionsSimpleApril 8, 2026

Counter Loading Screen

A numeric counter ticks from 0 to 100 during a loading screen using GSAP's object tweening, then the screen wipes away with a yPercent animation to reveal the page beneath.

View Full Demo →
0
index.jsx
"use client";

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

export default function CounterLoadingScreen({ duration = 2500 }) {
  const [count, setCount] = useState(0);
  const [done, setDone] = useState(false);
  const [hidden, setHidden] = useState(false);
  const screenRef = useRef(null);
  const countRef = useRef({ value: 0 });

  useEffect(() => {
    const obj = countRef.current;

    gsap.to(obj, {
      value: 100,
      duration: duration / 1000,
      ease: "power1.inOut",
      onUpdate() {
        setCount(Math.floor(obj.value));
      },
      onComplete() {
        setDone(true);
        // Wipe the screen away
        gsap.to(screenRef.current, {
          yPercent: -100,
          duration: 0.7,
          ease: "power3.inOut",
          delay: 0.1,
          onComplete: () => setHidden(true),
        });
      },
    });
  }, [duration]);

  if (hidden) {
    return (
      <div className={styles.revealed}>
        <p className={styles.revealedText}>Page revealed</p>
        <button
          className={styles.resetBtn}
          onClick={() => {
            setCount(0);
            setDone(false);
            setHidden(false);
            countRef.current.value = 0;
            const obj = countRef.current;
            gsap.to(obj, {
              value: 100,
              duration: duration / 1000,
              ease: "power1.inOut",
              onUpdate() { setCount(Math.floor(obj.value)); },
              onComplete() {
                setDone(true);
                gsap.to(screenRef.current, {
                  yPercent: -100,
                  duration: 0.7,
                  ease: "power3.inOut",
                  delay: 0.1,
                  onComplete: () => setHidden(true),
                });
              },
            });
          }}
        >
          Replay
        </button>
      </div>
    );
  }

  return (
    <div className={styles.wrapper}>
      <div ref={screenRef} className={styles.screen}>
        <span className={styles.counter}>{count}</span>
        <div
          className={styles.progress}
          style={{ transform: `scaleX(${count / 100})` }}
        />
      </div>
    </div>
  );
}
styles.module.css
.wrapper {
  position: relative;
  height: 400px;
  overflow: hidden;
  background: #f5f5f5;
}

.screen {
  position: absolute;
  inset: 0;
  background: #0d0d0d;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 2.5rem;
  gap: 1.5rem;
}

.counter {
  font-size: clamp(4rem, 15vw, 8rem);
  font-weight: 700;
  letter-spacing: -0.05em;
  color: #ffffff;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.progress {
  width: 100%;
  height: 1px;
  background: rgba(255, 255, 255, 0.4);
  transform-origin: left;
  transition: transform 50ms linear;
}

.revealed {
  height: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  background: #f5f5f5;
}

.revealedText {
  font-size: 1rem;
  color: #6b6b6b;
}

.resetBtn {
  padding: 0.625rem 1.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  font-family: inherit;
  color: #ffffff;
  background: #1a1a1a;
  border: none;
  border-radius: 9999px;
  cursor: pointer;
}
  • gsap

May 11, 2026

SECTIONS

Dual Push Cards

Two-up CTA card section with scroll-driven parallax on each card's background image. Cards scale down and drift vertically as you scroll past. Glassmorphic blur buttons at bottom-left. Stacks on mobile, side-by-side grid on desktop.

May 4, 2026

SECTIONS

Portfolio Grid

A responsive portfolio showcase section with a header tagline, blinking cursor counters, a 2-up/4-col project card grid with hover-zoom images and data-label metadata, plus a full-width CTA button. Scroll-triggered fade and move-up animations via GSAP.

May 1, 2026

SECTIONS

Logo Wall Cycle

A responsive logo grid that cycles through brand logos with smooth GSAP-powered swap animations. Shows 8 logos on desktop and 6 on tablet, shuffling hidden logos into view on a timed loop. Pauses when out of viewport or tab is hidden.