Text✨ Premium

Gravity Drop Text

Letters break free from the top of the scene, accelerate under gravity and bounce off the baseline before settling — pure physics, zero library.

JSPhysicsGravity

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →

3 usage examples

Launch hero — a word that asserts itself on screen — Gravity Drop Text example 1

① Launch hero — a word that asserts itself on screen

WhenOn load of a product launch page, marketing landing, or portfolio: the main title must make an impression from the first glance.
WhyGravity gives the word physical weight — it doesn't appear, it lands. The animation lasts under 2 s and leaves the scene silent afterward, with no looping that tires the eye.
SettingsShort uppercase word (5–8 letters), font-size: 4rem, 80 ms stagger, g ≈ 0.60 — full touchdown in ~1.2 s.
Long-form header — article title that falls onto the baseline — Gravity Drop Text example 2

② Long-form header — article title that falls onto the baseline

WhenOn load of a magazine article, annual report, or about page whose title is a single strong word: the animation replaces a plain fade-in.
WhyCascaded letters reveal the word progressively — each letter reinforces sequential reading. The restrained bounce stays compatible with a serious editorial context.
Settings7–9 letters, font-size: 3rem, font-weight: 800, 70 ms stagger, sober textual context surrounding the animated word.
Game title screen — VICTORY crashes into the scene — Gravity Drop Text example 3

③ Game title screen — VICTORY crashes into the scene

WhenAfter a win, level transition, or session start: the word drops with impact and amplifies the emotion of the moment before the Play Again CTA appears.
WhyThe physical bounce fits perfectly in a gaming context — without visual overload, the effect reads in under a second and gives way to the next UI elements.
SettingsAll-caps word, font-size: 3.5rem, gold or neon color, g ≈ 0.75 for a faster drop and sharper impact.

How it works

The splitChars() function reads the data-text attribute on the container and generates one <span class="char" data-char="…"> per letter. Each span is a display: inline-block — required for transform to apply independently per character.

A requestAnimationFrame loop animates each letter separately. Vertical velocity increases every frame by a gravity constant (g ≈ 0.60 px/frame). Position is applied via style.transform = 'translateY(' + y + 'px)' as an inline style — no CSS transition involved. Each letter starts at translateY(-220px), opacity: 0, and becomes visible on its first active frame.

On impact (y ≥ 0), velocity is reversed with damping (vy = −vy × 0.45) — the letter bounces upward then falls again with progressively shorter arcs until it comes to rest. The CSS keyframe @keyframes ktElastic (scaleY(0) scaleX(1.8)scaleY(1) scaleX(1)) is available to add a squash & stretch effect on landing via the active class.

Letters start in a cascade with a ~90 ms stagger per letter — early letters have already landed before the last ones begin to fall. A click listener on the container resets all letters to the top position and restarts the RAF loop.

Accessibility

  • prefers-reduced-motion: absent from the code — no branch stops or reduces the animation. To implement: detect matchMedia('(prefers-reduced-motion: reduce)').matches and place letters directly at translateY(0) without launching the RAF.
  • Text remains in the DOM as readable <span> elements — screen readers access the content independently of the animation.
  • user-select: none on .kt-text — letters are not cursor-selectable; not blocking for screen-reader accessibility.
  • Contrast: white text (#fff) on a dark background (#0a0a0f) — ratio ≥ 7:1, WCAG AAA.
  • The .kt-gravity container is clickable but has no role="button" or tabindex — the 'click to replay' feature is not keyboard-accessible; add both if needed.

Browser compatibility

Requires CSS Transforms and requestAnimationFrame — supported in all modern browsers. Zero external dependencies.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 15+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Touch OK
Android Chrome✓ Full

Without JS, letters stay invisible (<code>opacity: 0</code> set by <code>.kt-gravity .char</code>). Add a CSS fallback state or <code>&lt;noscript&gt;</code> if non-JS visitors are targeted.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="kt-text kt-gravity" id="gravity1" data-text="YOUR TEXT" style="cursor: pointer;">
  <!-- splitChars() generates one <span> per letter -->
  <span class="char" data-char="Y">Y</span>
  <span class="char" data-char="O">O</span>
  <span class="char" data-char="U">U</span>
  <span class="char" data-char="R">R</span>
</div>
<span class="demo-hint">Click to replay</span>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
data-text GRAVITY Text to animate — change the value on the .kt-gravity element to swap the word without touching JS.
font-size on .kt-text 2.2rem Letter size. Go up to 3–5rem for a hero impact; down to 1.5rem for a subtle UI integration.
color on .kt-text #fff Letter color. Accepts any CSS value — a gradient via background-clip: text is possible on the parent.
font-weight on .kt-text 800 Weight. 900 + a condensed font maximises the mass-on-landing feel.
letter-spacing on .kt-text 0.02em Letter spacing. Set to 0 or negative for a tight word; 0.1–0.2em to open it up.
gravity constant g (script) 0.60 Gravitational acceleration in px/frame². Raise to 0.8–1.0 for brutal impact; lower to 0.3–0.4 for a lunar feel.
bounce damping (script) 0.45 Restitution coefficient (0 = no bounce, 1 = perfect bounce). 0.3 = one dry bounce, 0.6 = several visible bounces.
stagger (script) 90 ms Delay between each letter's start. 50 ms = fast cascade, 150 ms = each letter lands before the next begins.

FAQ

Create as many .kt-gravity elements as needed, each with a unique id. Call the init logic once per element — the RAF loop runs independently for each instance.
Yes. Apply font-family to .kt-text. One precaution: load the font before starting the RAF (listen to document.fonts.ready) to avoid a font-flash during the first animation frames.
Yes — set the damping coefficient to 0 in the script: the letter stops cleanly at the baseline without going back up. Trigger ktElastic (CSS squash & stretch) at that point to simulate an impact without kinetic rebound.