Letters sliding in from top and bottom.
I was watching some movie yesterday, and one of the text effects they used in the intro had text flying in from top and bottom. Although I feel like this version actually looks a little better (see demo.)
This effect has three moving parts: splitting the word into individual letters, assigning alternating directions, and staggering the timing so the letters cascade in one by one.
The trick starts in JavaScript. Instead of rendering the word as plain text, we loop over each character and wrap it in its own <span>:
word.split("").forEach((char, i) => {
const span = document.createElement("span");
span.textContent = char;
span.classList.add("letter");
// ...
container.appendChild(span);
});
This gives us independent control over every letter's position and timing — something you can't do with a single text node.
Each letter gets either from-top or from-bottom based on whether its index is even or odd:
span.classList.add(i % 2 === 0 ? "from-top" : "from-bottom");
That's the whole secret to the interleaved look. Letters at positions 0, 2, 4 fall from above; letters at 1, 3, 5 rise from below. The classes map to two keyframe animations that are mirrors of each other — one starts at translateY(-200px), the other at translateY(200px), and both land at translateY(0).
If all the letters animated at once it would feel like a single blob flying in. The stagger is what makes it feel like a cascade:
span.style.animationDelay = `${i * 0.07}s`;
Each letter waits 70ms longer than the previous one. Tighten this value (say, 0.04s) for a faster sweep; widen it for a more dramatic, drawn-out reveal. All letters start at opacity: 0 in CSS so nothing flashes before its delay fires.
A straight ease-out landing feels flat. The keyframe adds a small overshoot past center, then snaps back, giving the letters a satisfying physical "clunk":
@keyframes slideFromTop {
0% { opacity: 0; transform: translateY(-200px); }
60% { opacity: 1; transform: translateY(10px); } /* overshoot */
80% { transform: translateY(-5px); } /* bounce back */
100% { opacity: 1; transform: translateY(0); } /* settle */
}
The letter arrives slightly past its target at 60%, rebounds a few pixels at 80%, then settles at 0. The from-bottom keyframe is the vertical mirror of this (negative values become positive and vice versa).
The full effect is pure CSS animations driven by a tiny bit of JS to inject the spans and delays — no animation library needed. To adapt it to your own word, swap out the word string and optionally tune the two knobs: animationDelay multiplier for timing and the translateY overshoot values for the feel of the landing.