Text✨ Premium

Letter Slide Up

Each letter rises from below with a regular stagger — pure CSS animation that gives depth to any heading.

JSCSSSlide

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

Landing hero — The main headline enters the scene — Letter Slide Up example 1

① Landing hero — The main headline enters the scene

WhenThe page loads and the main headline reveals itself letter by letter — visitors watch the message settle rather than appearing all at once.
WhyThe progressive rise adds rhythm without distracting from the message: each arrived letter holds its place, the whole line stays readable at every frame.
SettingsStagger 0.08 s for ≥ 8 letters, duration 0.5 s, font-size 4–6 rem, font-weight 900.
Portfolio & magazine — Section heading triggered on scroll — Letter Slide Up example 2

② Portfolio & magazine — Section heading triggered on scroll

WhenA new section of a long article or portfolio enters the viewport — the heading animates exactly as it comes into view, via an IntersectionObserver.
WhyThe upward movement of the letters mirrors the scrolling metaphor itself: the effect is contextual, not decorative.
SettingsStagger 0.04 s (long text), duration 0.35 s, translateY 60% for a subtle touch, font-size 2 rem, letter-spacing 0.05 em.
Welcome screen — App name on launch — Letter Slide Up example 3

③ Welcome screen — App name on launch

WhenThe app opens and the product name displays letter by letter before the rest of the UI — an identity moment before the functional interface.
WhyOne animation, one word: the rising letters create a memorable instant and raise the perceived quality of the product without any technical complexity.
SettingsStagger 0.09 s, duration 0.5 s, overflow: hidden on the parent to clip the travel, font-size 3 rem, font-weight 900, letter-spacing 0.15 em.

How it works

The slideUpLetter keyframe moves each letter from opacity: 0; transform: translateY(100%) to its natural state in 0.4 s, with animation-fill-mode: forwards holding each letter visible on arrival. Wrapping each character in a <span> set to display: inline-block is required: inline elements ignore CSS transforms.

The splitText(el, text, delay) function slices the text character by character and injects one <span> per letter into the target element. Each span gets an animation-delay of index × delay seconds (0.06 s by default). Spaces increment the counter without creating a span, producing a short pause in the cascade — visually, spaces appear to arrive too.

To replay: replaySlideUp() clears innerHTML, waits 50 ms for the browser to invalidate previous animation states, then calls splitText again. At initial load, spans are pre-built in the HTML with inline animation-delay attributes, triggering the animation on first render without any JS call.

Accessibility

  • prefers-reduced-motion absent: no @media (prefers-reduced-motion: reduce) block in the delivered CSS — the animation plays even when the OS requests reduced motion. Add that block to set letters directly to opacity: 1; transform: none.
  • Animated text is real text content, not a canvas or image — screen readers read the letters normally, no aria-* attributes are needed.
  • The Replay button is a native <button>, keyboard-focusable (Tab + Enter or Space).
  • Contrast: white text (#fff) on background #0a0a0f, ratio ~21:1 — well above the WCAG AA threshold (4.5:1).
  • No role or aria-label is defined by the effect: since the content is readable text, native semantic rendering is sufficient.

Browser compatibility

Requires CSS @keyframes and basic DOM manipulation (innerHTML, createElement) — supported in all modern browsers. Zero external dependencies.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 13.1+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

If CSS animations are unsupported (very old browser), all letters stay at <code>opacity: 0</code> — the text is invisible but no JS errors are thrown.

The code

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

index.html — structure
<div class="demo-preview">
  <span class="demo-text text-slide-up" id="slideUpText">
    <!-- splitText(el, "Your text", 0.06) generates these spans -->
    <span style="animation-delay: 0s">Y</span>
    <span style="animation-delay: .06s">o</span>
    <!-- … one &lt;span&gt; per letter, spaces as plain text … -->
  </span>
  <button class="replay-btn" onclick="replaySlideUp()">Replay</button>
</div>
🔒 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
Stagger delay 0.06 s per letter 3rd argument of splitText(el, text, delay) — increase (0.10 s) to space out letters, decrease (0.03 s) for 15+ character text.
Animation duration 0.4 s Value 0.4s in the CSS rule .text-slide-up span — 0.6 s for smoother entry, 0.2 s for a quick flash.
Starting offset translateY(100%) Property transform: translateY(100%) in .text-slide-up span — reduce to 60% for a subtle touch; add overflow: hidden to the parent to clip the travel.
Easing ease Value ease in animation: .4s ease — swap for cubic-bezier(0.22, 1, 0.36, 1) for a gentle overshoot, or linear for a constant rise.
Font size 2.5 rem font-size in .demo-text — 3–6 rem for a full-screen hero, 1.5–2 rem for editorial text.
Font weight 800 font-weight in .demo-text — 900 for maximum impact, 400 for light editorial text.
Letter spacing −0.02 em letter-spacing in .demo-text — increase to 0.05–0.15 em for an airy display type look.
Button accent color #818cf8 CSS variable --primary-light in :root — replace with your brand color for the Replay button.

FAQ

splitText is a shared utility across the Effect.Labs text effects. For standalone use, add it before the IIFE: function splitText(el,text,delay){el.innerHTML='';text.split('').forEach(function(ch,i){if(ch===' '){el.appendChild(document.createTextNode(' '));}else{var s=document.createElement('span');s.textContent=ch;s.style.animationDelay=(i*delay)+'s';el.appendChild(s);}});}
Yes. The CSS .text-slide-up span applies to any element carrying that class. For multiple instances, write a factory: function makeSlideUp(id,text,delay){var el=document.getElementById(id);splitText(el,text,delay||0.06);return function(){el.innerHTML='';setTimeout(function(){splitText(el,text,delay||0.06);},50);}} Call var replay=makeSlideUp('myId','My title',0.06) per element.
Leave the .text-slide-up element empty in the HTML (no pre-built spans). Wire an IntersectionObserver to it: when it enters the viewport, call splitText(el, 'Your title', 0.06) — spans are injected and the CSS animation starts immediately, without modifying the CSS or keyframe.