HeroesSimpleApril 8, 2026
Header Text Line Reveal
Header text lines slide up from below overflow-hidden parent containers on mount. Each line is clipped by its outer container and animates in with a slight stagger using GSAP.
View Full Demo →Preview
Crafting digital
experiences that
move people.
No-5 Studio — motion-forward web design for ambitious brands.
Source
index.jsx
"use client";
import { useEffect, useRef } from "react";
import gsap from "gsap";
import styles from "./styles.module.css";
export default function HeaderTextLineReveal({ lines = [], subtitle = "" }) {
const containerRef = useRef(null);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const lineEls = el.querySelectorAll(`.${styles.lineInner}`);
gsap.from(lineEls, {
yPercent: 110,
duration: 1,
stagger: 0.08,
ease: "power3.out",
delay: 0.1,
});
}, []);
return (
<header ref={containerRef} className={styles.header}>
<div className={styles.lines}>
{lines.map((line, i) => (
<div key={i} className={styles.lineOuter}>
<span className={styles.lineInner}>{line}</span>
</div>
))}
</div>
{subtitle && <p className={styles.subtitle}>{subtitle}</p>}
</header>
);
}
styles.module.css
.header {
min-height: 60vh;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 4rem 3rem 3rem;
background: #0d0d0d;
}
.lines {
display: flex;
flex-direction: column;
gap: 0;
}
/* Overflow-hidden clips the sliding text */
.lineOuter {
overflow: hidden;
display: block;
}
.lineInner {
display: block;
font-size: clamp(2.5rem, 7vw, 5.5rem);
font-weight: 700;
letter-spacing: -0.04em;
color: #ffffff;
line-height: 1.05;
}
.subtitle {
margin-top: 2rem;
font-size: 0.9375rem;
color: rgba(255, 255, 255, 0.45);
max-width: 40ch;
line-height: 1.65;
}
Dependencies
gsap