147

Text Roll Hover

£7 or the whole Vault, £79.20

Nav links and button labels that roll over letter by letter like little lit cubes, built on GSAP SplitText, reacting to how fast the pointer arrives and rippling into neighbouring links.

SplitText beginner
8 more details
text-animationhover-effectmicro-interactionstagger3d-transformsvelocity-reactiveinterruptible-transitionskeyboard-navigation

This demo reads better at your own screen size than in the frame below:

Released

About this effect

Text Roll Hover turns the label of any link or button into a row of small cubes. Hover it and each letter turns over, one after another, to a second face carrying the same word in your accent colour, or a different label such as "Start a project" becoming "Say hello". The faces are lit as they turn: the old word falls into shadow as it rolls away and the new one catches the light just before it lands, so it reads as a solid object rather than a colour change. It is built on GSAP SplitText, so the text stays real, selectable and read once by screen readers.

Read the full effect overview

The roll answers the pointer. A slow hover gives one gentle turn; a quick flick spins past flat and settles back. In a navigation row, hovering one link tips its neighbours a few degrees toward the turn, so a sweep along the menu travels as a wave. A click spins the label once round before the link is followed, and the link for the current page rests on its second face and rolls the other way when hovered. Eight presets give a choice of character: a vertical cube roll, a horizontal flip, a masked drop where the new word falls in from above, a slide that shunts the letters along in the direction the pointer travelled, a crisp editorial split where each letter's top and bottom halves part and rejoin, a fold where letters hinge down toward you as the next face stands up, a coin spin, and a wave that keeps one face and sends a lift and a flash of accent colour through the word.

Text Roll Hover - GSAP animation effect preview

What's included

13 items
  • Built on GSAP SplitText: one data attribute splits a label into letters
  • Letters turn as lit 3D cube faces: shadow as a face turns away, a glint as the next one lands
  • Pointer speed sets the turn: a slow hover settles gently, a fast flick overspins and settles back
  • Neighbouring links in a nav tip toward the hovered one, so a sweep reads as a wave
  • A click spins the label once round before the link is followed; modifier and middle clicks are left alone
  • The current page's link rests on its rolled face and rolls the other way on hover
  • Stagger follows the pointer: rolls in from the entry side, back from the exit side
  • Optional alternate label, with the element sized to the longer of the two so nothing shifts
  • Eight presets: roll, flip, drop, slide, split, fold, spin and wave, all staggered from the entry side and all settling exactly flat
  • Wave preset for links that should keep one label: letters rise in a travelling wave and flash the accent colour at the crest
  • Keyboard focus rolls like a slow hover; on touch a tap plays one roll before following the link
  • Reduced motion swaps every movement for a short colour fade
  • Small API to set up new markup, rebuild after a text change, and revert cleanly

Perfect for

4 use cases
  • Site headers and navigation rows that need a little character
  • Primary call-to-action buttons that change their wording on hover
  • Oversized footer headings and contact links that reward a hover
  • Inline text links such as "View case study" in a card grid

How it works

2 sections

GSAP SplitText breaks each label into letters twice: once for the word you see and once for a second face hidden just out of view. On hover, each letter turns a quarter turn around a point behind it, so the old letter rolls away as the new one rolls into place, with a short stagger measured from the side the pointer entered. The other presets swap the turn for a different move: letters pushed sideways through a mask, halves sliding apart and back together, a fold on the baseline, a coin spin, or a lift that travels through the word without changing it. How fast the pointer arrived decides how far the move runs past flat before it settles, within a fixed limit so it always lands on the right face; on the wave it sets how high the letters rise.

Each face is shaded by its angle as it turns and returns to exactly its own colour when flat, so contrast at rest is unchanged. Links that share a navigation row pass a small nudge to their neighbours, fading with distance. A click plays one quick spin and follows the link straight after it. Both faces share the same space, so the element keeps the width of the longer label and the layout never moves. Screen readers hear the label once, keyboard focus and touch taps play the same roll, and reduced motion replaces all movement with a quick fade to the accent colour. Without JavaScript the links are plain links.

Plugins SplitText
Difficulty Beginner
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this effect's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Paid effect

Purchase to unlock the code.

Buying Text Roll Hover opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£7 Standard license, unlimited projects

Browse free effects

Or the whole library: the Vault, £79.20, one payment.

Documentation

How it behaves

  • Lit faces. As a letter turns, the outgoing face falls into shadow toward its edge and the incoming face catches a glint of light just before it lands flat. A flat face is always exactly its own colour, so contrast at rest is unchanged. Roll, flip and fold are lit; the other presets are not.
  • Speed-sensitive spin. How fast the pointer arrives sets the turn. A slow hover gives one gentle quarter turn; a quick flick overspins past flat (never more than 1.3 quarter turns) and settles back onto the second face. Keyboard focus always uses the gentle turn.
  • Ripple to the neighbours. In a group of links, hovering one tips the letters of the two links either side a few degrees toward the turn, fading with distance, and they settle flat again. A sweep along a nav reads as a wave. A link that is not hovered never fully rolls.
  • Press. A click spins the label once round (about 0.35s) and then follows the link. Navigation waits only for that spin; Cmd, Ctrl, Shift and Alt clicks and middle clicks are left to the browser.
  • Current page. A link with aria-current="page" rests on its second face, and hovering it rolls back to the label and forth again the other way.

Presets

Set data-tr-preset on the element. Every preset staggers from the side the pointer came in, can be reversed mid-way, and settles exactly flat.

Preset What it does Overspin Ripple Press Current page
roll (default) Letters turn vertically on a lit cube, like a counter Yes Tips the cube One full turn Rests on the second face
flip The same cube turned sideways Yes Tips the cube One full turn Rests on the second face
drop Letters fall out of the bottom of a mask as the new ones drop in from the top (no 3D) No Nudges down Two drops Rests on the second face
slide Letters are pushed sideways in the direction the pointer travelled, the new face sliding in behind each one through a mask, so the word shunts along a track A small overshoot that settles back Nudges along the track Shunts round once and back Rests on the second face
split Each letter is cut at mid-height; the top half slides with the pointer and the bottom half against it, both masked, and the second face's halves slide in and rejoin A small overshoot past the join Shears the halves slightly Splits round once and back Rests on the second face
fold Hinged on the baseline, each letter folds down toward you as the second face stands up from behind it, with a short settle; lit Yes Tips the flap Folds round once and back Rests on the second face
spin Each letter spins once on its vertical axis like a coin, showing the second face from the moment it is edge on A touch more turn that settles back A small coin wobble One more coin turn of the face showing Rests on the second face
wave No face swap: letters rise and stretch slightly in a wave that travels from the entry side, taking the accent colour at the crest, then fall back to ink A faster entry lifts the wave higher instead Neighbours rise a little One quick wave Has no rolled face, so the current link stays in the accent colour and its wave keeps the accent at the crest

Notes:

  • wave keeps one face. It ignores data-tr-alt and data-tr-light, and leaving the link sends a smaller wave back from the exit side. Use it for links whose label should never change.
  • slide and split follow the direction of travel. Coming in from the left pushes the letters right; leaving through the far side keeps them moving the same way, and leaving back through the side you came in reverses them. A turn interrupted part way retraces its path.
  • spin shows the back of the coin mirrored while it turns, and its press turns the face that is showing once round without swapping.
  • Only roll, flip and fold are lit. data-tr-light does nothing on the others.
  • Reduced motion is the same short fade for every preset (see Accessibility).

Quick Start

1. Add to your HTML <head>:

Code snippet omitted: it ships with the download.

2. Add before the closing </body> tag:

Code snippet omitted: it ships with the download.

3. Add data-tr to any link, button label or heading link in your <body>:

Code snippet omitted: it ships with the download.

Every [data-tr] element on the page is set up when the script loads.

Using It With Your Own Design

What the effect needs from your markup: an element with data-tr whose content is the label text. Put it on the link itself, or on a <span> inside a link or button when the control also holds an icon: the roll is triggered by the nearest link or button around it, so hovering anywhere on the button rolls the label. Keep icons outside the data-tr element, since everything inside it is split into letters.

What is only the demo's styling: everything below the "Demo page" line in style.css (the specimen stage: link row, pill button, large heading, fonts and palette) and the preset switcher block at the end of script.js. Delete them freely.

Groups for the ripple: links inside the same nav, menu, ul, ol or [role="navigation"]/[role="menubar"] ripple into each other in document order. Put data-tr-group on any other wrapper to make its links a group, for example a row of footer links in a div. A single link, or links in running text, are not grouped.

Client-side routers: the press spin holds a plain left click for about 0.35s and then follows the link with a normal page load. If your site navigates with a client-side router, set data-tr-press="off" on its links so the router keeps control of the click. A click another script has already cancelled is never followed.

CSS the effect depends on: the rules above the "Demo page" line. .tr-stack and .tr-face stack both faces in one grid cell so the element is as wide as the longer label (split draws each face twice, as .tr-face--upper and .tr-face--lower, cut apart only while letters move); .tr-word, .tr-char and .tr-char-mask must stay inline-block, because transforms and masks do nothing on inline boxes; backface-visibility: hidden keeps the waiting face invisible; .tr-sr is the visually hidden label copy and must stay hidden visually but not with display: none. Letters rise a little above the line while they turn (and fold reaches a little below it): give large headings room, or clip the turn to the line box as the demo's large heading does. Set --tr-accent on any ancestor to recolour the second face, for example on a dark button. The lighting mixes each face toward --tr-light and --tr-shadow while it turns, so it works on light and dark grounds alike; on a coloured ground you can point --tr-shadow at a deep shade of that colour.

Choosing a typeface

Splitting text into letters drops kerning pairs and ligatures, so the stylesheet turns them off on [data-tr] from the start and nothing shifts when the split lands. Grotesques and geometric sans faces with modest kerning (Mona Sans, Inter, Helvetica-style faces) look identical either way and suit the effect at every size. Script faces, connected lettering and display serifs that rely on tight kerning pairs or ligatures (such as "fi" or "ffl") will look looser once split: check them at your largest size before using them.

Options

Attribute Values Default Description
data-tr none Marks an element whose label rolls
data-tr-preset roll, flip, drop, slide, split, fold, spin, wave roll How the letters move; see Presets
data-tr-alt Any text Same label The label on the second face (ignored by wave)
data-tr-duration Seconds 0.34 How long each letter takes to turn
data-tr-stagger Seconds 0.024 Gap between neighbouring letters; long labels compress it so the whole word lands within 0.7s
data-tr-trigger none Put on a wrapper (not a link or button) to make the whole wrapper the hover area for a data-tr inside it
data-tr-light 0 to 1.5 1 Strength of the face lighting on roll, flip and fold; 0 turns it off
data-tr-overspin 0 to 0.3 0.3 How far past flat, in quarter turns, a fast flick may spin before it settles; 0 keeps every hover gentle. Slide, split, fold and spin use a share of it; on wave it sets how much higher a fast entry lifts; drop ignores it
data-tr-group none Marks a wrapper whose data-tr links ripple into each other (nav, menu and list elements already do)
data-tr-ripple Degrees 14 How far the nearest neighbour tips (the next one tips less). Put it on a link or a group; 0 turns the ripple off
data-tr-press off on off removes the click spin and the short navigation hold
CSS custom property Default Description
--tr-accent #00784a Colour of the second face
--tr-depth 0.5em Half the cube's size: how far behind each letter it turns (roll and flip). Lower it for tightly tracked display type
--tr-align center Where the shorter of two labels sits inside the longer one (start, center, end)
--tr-light #fff What a face catching the light mixes toward
--tr-shadow #000 What a face turning away mixes toward

The link for the current page needs no option: give it aria-current="page", as you would for screen readers anyway.

Accessibility

  • Screen readers hear the label once. Each element gets a visually hidden copy of its original text, and the split letters and the second face are hidden from assistive technology, so the accessible name comes from the content and matches the visible label (voice control users can say what they see). An alternate label is visual only.
  • Keyboard: focusing a link or button with the keyboard rolls it like a slow hover (and nudges its neighbours), and moving focus away rolls it back. Enter plays the press spin before the link is followed. A mouse click does not leave it rolled after the pointer leaves.
  • Touch: there is no hover state to get stuck. A tap plays one roll (not the press spin), starting from the side you tapped, and then follows the link. Links that open in a new tab or carry download are followed immediately and still roll.
  • Reduced motion: with prefers-reduced-motion: reduce nothing turns, slides, tips or spins in any preset, and links are followed at once; the second face fades in over the label in the accent colour (or, on the current page's link, the label fades back in). On wave this is a fade to the accent colour. Changing the setting while the page is open rebuilds every label.
  • No JavaScript, or GSAP blocked: the links are left exactly as written.

Dependencies

Required:

  • GSAP 3.13+ (the demo is pinned to 3.15.0)
  • SplitText plugin (free with GSAP since 3.13)

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.