Text✨ Premium

Flip Characters

Each character flips around its horizontal axis on hover — the cascade ripples letter by letter through a staggered CSS delay calculated by the JS at init.

CSSHover3D

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

Studio headline — Animated typographic identity — Flip Characters example 1

① Studio headline — Animated typographic identity

WhenA creative studio, agency, or portfolio home page presents its name or tagline as a large interactive heading.
WhyOn a large surface with a heavy typeface, the letter-by-letter flip cascade reinforces brand identity and immediately signals interactivity — the stagger shines on longer titles.
Settingsfont-size 5–7 rem, font-weight 900, animation-delay increment 0.04 s/char to keep the cascade snappy on long words, letter-spacing -0.03em.
Primary navigation — Menu items that flip on hover — Flip Characters example 2

② Primary navigation — Menu items that flip on hover

WhenA site nav bar contains 4–6 short links (Home, Projects, About, Contact). Each label flips on hover.
WhyShort words (3–7 letters) produce an ultra-fast, precise cascade — the micro-interaction is elegant without ever hindering legibility. The text is always readable and the click target never moves.
Settingsfont-size 1.1 rem, font-weight 600, animation duration 0.4 s, stagger 0.03 s/char, brand primary text color.
Project or category card — Label whose letters flip — Flip Characters example 3

③ Project or category card — Label whose letters flip

WhenA grid of projects, products, or articles displays names or short category labels. Hovering the card reveals the animation on the title.
WhyFlipping a short word or number (e.g. "DESIGN", "2025") produces a clean, memorable effect without overloading the content. Works equally well in monochrome or color, on dark or light backgrounds.
Settingsfont-size 2–3 rem, font-weight 800, stagger 0.05 s/char (default), combine with a slight opacity 0.7 → 1 on the card hover to coordinate the reveal.

How it works

On load, the script targets the element with id="flipText", reads its text content, and reinjects each character into an individual <span> via innerHTML. Each span receives a style="animation-delay: Ns" computed at 0.05 s × index — that is the sole responsibility of the JS; everything else is pure CSS.

The flipChar keyframe rotates the span around the X axis (rotateX): 0° → 90° → 0°. At 90° the character is seen edge-on and nearly disappears, then returns flat — the eye reads it as a flip. The display: inline-block on each span is mandatory: without it, transform has no effect on inline elements.

The trigger is .text-flip:hover span: hovering the parent container fires the animation on all spans at once, but the staggered delays produce the letter-by-letter cascade. Total cascade duration is approximately (n − 1) × 0.05 s + 0.6 s, where n is the character count.

The transition: transform 0.3 s on each span handles the return to rest when the mouse leaves the container — letters snap back smoothly without replaying the full keyframe.

Accessibility

  • prefers-reduced-motion absent: the code contains no prefers-reduced-motion media query. The flipChar animation fires even when the user has enabled reduced motion in the OS — add manually if needed: @media (prefers-reduced-motion: reduce) { .text-flip:hover span { animation: none; } }.
  • The text remains native DOM text wrapped in spans — screen readers read the original content without disruption, unlike a canvas or an image.
  • Keyboard only: the effect is triggered by :hover, not :focus-within. Keyboard-only users (Tab navigation) do not see the animation. Add .text-flip:focus-within span to the animation rule to fix this.
  • Contrast: the effect defines no colors — the contrast ratio depends entirely on the implementation. Verify WCAG AA (≥ 4.5:1) against the chosen background.
  • The animation lasts 0.6 s and does not loop (iteration-count: 1, fill-mode: forwards) — it does not constitute auto-playing animated content under WCAG 2.2.2 (no looping without interaction).

Browser compatibility

Requires CSS 3D transforms and CSS animations — supported since Chrome 36, Firefox 16, Safari 9. Zero external dependencies.

Chrome 80+✓ Full
Firefox 72+✓ Full
Safari 13+✓ Full
Edge 80+✓ Full
Mobile iOS✓ Hover inactive (touch)
Android Chrome✓ Hover inactive (touch)

Without <code>rotateX</code> support, letters stay flat — the text is perfectly readable. On mobile (no hover), characters display normally with no animation.

The code

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

index.html — structure
<div class="demo-preview">
  <!-- JS splits textContent into spans with animation-delay on load -->
  <span class="demo-text text-flip" id="flipText">YOUR TEXT</span>
  <!-- After JS init, becomes: -->
  <!-- <span class="demo-text text-flip" id="flipText">
    <span style="animation-delay: 0s">Y</span>
    <span style="animation-delay: 0.05s">O</span>
    ...
  </span> -->
</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
font-size on .demo-text 2.5 rem Character size — increase to 4–7 rem for a hero heading, reduce to 1 rem for navigation.
font-weight on .demo-text 800 Text weight. 900 accentuates the flip (wider character); 400 gives a thinner, subtler flip.
animation-delay: ${0.05 × t}s in JS (calc line) 0.05 s/char Stagger increment between each letter. Reduce to 0.03 s for a fast cascade on long words; increase to 0.08 s for a slow, dramatic effect.
duration in .text-flip:hover span (animation: .6s) 0.6 s Duration of a single character flip. 0.3 s = snappy; 1 s = slow and cinematic.
transition in .text-flip span (transition: transform .3s) 0.3 s Return-to-rest speed when the mouse leaves. Reduce to 0.1 s for an immediate snap.
rotateX in @keyframes flipChar at 50% rotateX(90deg) Flip axis. Replace with rotateY(90deg) for a lateral (left–right) flip instead of vertical.
perspective on .text-flip (to add) none Adding perspective: 300px on the parent .text-flip adds a pronounced 3D depth to the flip.
letter-spacing on .demo-text -0.02 em Letter spacing. Increasing to 0.1–0.2 em spaces out the cascade and makes each individual flip more distinct.

FAQ

The script targets getElementById('flipText') — one element per page. For multiple instances, replace the lookup with querySelectorAll('.text-flip') and iterate: document.querySelectorAll('.text-flip').forEach(el => { el.innerHTML = el.textContent.split('').map((c, i) => `<span style="animation-delay:${i*.05}s">${c}</span>`).join(''); }).
Not natively — the :hover trigger does not fire on touch devices without a pointer. For touch interaction, add a touchstart listener that toggles a .flipping class on the element and trigger the animation through that class instead of :hover.
Add the rule: @media (prefers-reduced-motion: reduce) { .text-flip:hover span { animation: none; } }. The text remains readable and interactive without the flip animation.