webdevpuneet.com

Letter Gravity Drop Text Animation — Bounce Physics JS

Letter Gravity Drop Text · Animations · Plain HTML, CSS & JS · Live preview

CategoryAnimations

Copy & paste

Source Code

<div class="scene">
  <h1 class="gravity-heading" id="heading">Letters fall into place</h1>
  <button class="replay" onclick="dropLetters()">Drop again</button>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real velocity/acceleration simulation per letter, not a sampled easing curve
requestAnimationFrame loop with delta-time integration for frame-rate independence
Bounce damping (velocity reversed and reduced) produces diminishing bounce heights
Per-letter independent physics state — staggered starts never desync existing bounces
GRAVITY, BOUNCE_DAMPING and stagger interval are single tunable constants
Splits any headline into per-letter spans automatically, with space handling
Replay button resets every letter above the baseline and reruns the cascade
Zero dependencies — no physics or animation library required
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons

About this UI Snippet

Letter Gravity Drop Text — Gravity Acceleration, Bounce Damping & requestAnimationFrame

Screenshot of the Letter Gravity Drop Text snippet rendered live

A letter gravity drop animates each character of a headline falling from above the baseline under simulated gravity, bouncing once or twice off the resting position with diminishing height, and settling — the way a dropped ball behaves, applied to typography. It reads as more physically grounded than a CSS ease-out, because the motion is computed frame by frame from actual velocity and acceleration rather than sampled from a fixed easing curve. For a rotational, hinge-style entrance instead of a vertical drop, see 3D character flip reveal; for a scale-based spring instead of gravity, see word spring bounce heading.

Splitting into letters and priming them off-screen

buildLetters(el) wraps every character of the heading in its own <span class="letter">, converting spaces to non-breaking spaces so word gaps hold their width. Before dropping, dropLetters() sets every letter's opacity to 0 and transform to translateY(-260px) — parking each letter well above its resting line, invisible, ready to fall.

Simulating gravity with velocity and acceleration

Rather than a CSS @keyframes curve, each letter's fall is computed manually inside a requestAnimationFrame loop. velocity += GRAVITY * dt accelerates the letter downward every frame (GRAVITY = 2600, an arbitrary pixels/second² constant tuned for a snappy but visible fall), and y += velocity * dt integrates that velocity into a position update. dt is the real elapsed time since the previous frame ((now - last) / 1000, clamped to avoid a huge jump after a tab is backgrounded), so the fall speed is consistent regardless of the display's refresh rate.

The bounce

When y >= restY (the letter has reached or passed its resting baseline), the code clamps y back to restY and reverses the velocity with damping: velocity = -velocity * BOUNCE_DAMPING (BOUNCE_DAMPING = 0.42). Because the reflected velocity is smaller than the impact velocity, each successive bounce is lower than the last — exactly like a real dropped object losing energy to an inelastic surface. The loop keeps bouncing until the velocity magnitude falls below a small threshold or a bounce-count cap is hit, at which point it snaps to exactly translateY(0px) and resolves.

Staggering the drops

dropLetters() calls animateDrop(l, i * 45) for every letter, delaying the start of each letter's fall by 45ms times its index via setTimeout. Because each letter runs its own independent requestAnimationFrame loop with its own velocity state, letters that start falling later do not interfere with ones already bouncing — the whole headline settles in a cascading, slightly chaotic rhythm rather than a mechanically uniform one.

Step by step

How to Use

  1. 1
    Watch it load, then replayLetters fall in with a bounce on page load. Click "Drop again" to reset every letter above the line and replay the cascade.
  2. 2
    Change the headline textEdit the text inside #heading in the HTML panel — buildLetters() re-splits it into per-letter spans on load.
  3. 3
    Adjust the fall strengthIn the JS panel, increase GRAVITY for a faster, snappier fall or decrease it for a slower, floatier one.
  4. 4
    Change how bouncy letters areUpdate BOUNCE_DAMPING (0 to 1) — closer to 1 means more energy is retained and letters bounce more times before settling.
  5. 5
    Adjust the stagger between lettersChange the 45 multiplier in animateDrop(l, i * 45) inside dropLetters() to speed up or slow down the cascade.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Playful brand and game landing pages
Gravity-driven letter drops fit playful, energetic brands — casual games, kids products, and consumer apps that want typography with a sense of physical fun.
Splash and loading screen headlines
Drop a wordmark or tagline into place as the first thing a user sees, giving the loading moment some visual interest instead of a static logo.
Learn requestAnimationFrame physics simulation
Edit GRAVITY and BOUNCE_DAMPING directly in the JS panel to see how tuning two constants changes the entire feel of a physics-driven animation.
Celebration and success-state messaging
Use on a "Success!" or "You won!" headline after a completed action — the bounce reinforces a rewarding, celebratory moment.
Pair with confetti or particle effects
Combine with a particle burst timed to each letter's final bounce for a more elaborate celebration sequence.
Interactive teaching or physics demos
Because the motion is a genuine (if simplified) gravity simulation, this doubles as a teaching example for velocity, acceleration, and energy loss on bounce.

Got questions?

Frequently Asked Questions

It is a genuine (simplified) simulation. Each letter has its own velocity that increases every frame by GRAVITY * dt, and position that increases every frame by velocity * dt — real numerical integration, not a value sampled from a fixed bezier curve. This is what allows the bounce to look organic rather than mechanically repeating.

When a letter's falling position reaches its resting line, its velocity is reversed and multiplied by BOUNCE_DAMPING (0.42), which is less than 1. Each bounce therefore launches the letter upward with less speed than it landed with, so peak height decreases every bounce until the velocity drops below a stop threshold.

Delta time (now - last) / 1000 measures real elapsed seconds between frames, so the fall speed stays consistent whether the display runs at 60Hz, 120Hz, or drops frames under load. A fixed per-frame step would make the animation run at different real-world speeds on different devices.

Staggering the start time with i * 45ms per letter index creates a cascading left-to-right rhythm. Each letter runs an independent physics loop with its own velocity and position state, so staggering starts never causes two letters to fight over the same animation state.

Increase BOUNCE_DAMPING toward 1 for more bounces retaining more energy each time; decrease it toward 0 for a fall that barely bounces at all and settles almost immediately on impact.

Yes. Click "JSX" for a React component. Store each letter's DOM node in a ref array, run the same requestAnimationFrame velocity loop inside a useEffect triggered by a "play" trigger prop, and clean up any pending animation frames on unmount.