▚◆VAULT/#%
INTERACTION_044CSS + JS
Scrambled Text Reveal
The whole string shuffles and settles like a mechanical board.
Text / LightView
A heading wipes into view as its clip rectangle opens left to right. Clipped to zero width with inset(0 100% 0 0) before the trigger; animating the clip inset from 100% to 0 once the heading enters view.
/* Clip Path Heading Reveal — A heading wipes into view as its clip rectangle opens left to right. */
.clip-path-heading-reveal {
--dur: 700ms;
--ease: cubic-bezier(0.22, 1, 0.36, 1);
--stagger: 60ms;
will-change: transform, opacity;
}
.clip-path-heading-reveal > * {
opacity: 0;
transform: translateY(14px);
animation: clip-path-heading-reveal-in var(--dur) var(--ease) forwards;
animation-delay: calc(var(--i, 0) * var(--stagger));
}
/* clipped to zero width with inset(0 100% 0 0) -> animating the clip inset from 100% to 0 */
@keyframes clip-path-heading-reveal-in {
to {
opacity: 1;
transform: none;
filter: none;
}
}
@media (prefers-reduced-motion: reduce) {
.clip-path-heading-reveal > * {
opacity: 1;
transform: none;
animation: none;
}
}import { useEffect, useRef } from "react";
/** Clip Path Heading Reveal — trigger: the heading enters view */
export function ClipPathHeadingReveal({ children }: { children: React.ReactNode }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
el.dataset["state"] = "in";
return;
}
const io = new IntersectionObserver(
([entry]) => {
if (entry?.isIntersecting) {
el.dataset["state"] = "in";
io.unobserve(el);
}
},
{ threshold: 0.2 },
);
io.observe(el);
return () => io.disconnect();
}, []);
return (
<div ref={ref} className="clip-path-heading-reveal" data-state="out">
{children}
</div>
);
}The whole string shuffles and settles like a mechanical board.
Copy resolves from a soft blur into perfect focus as it enters view.
Each line slides up from behind an invisible mask, one after the other.
Words fade up in sequence so the sentence assembles as you read it.