rotating-text
v1.3.0
Published
3D Rotating Text Component for React
Readme
Rotating Text
Customizable 3D text hover animation. Moves on Framer Motion's springs, built in, so React is its only dependency. Respects user's Reduced Motion preferences.
See it live at rotating-text.vercel.app, with a playground to try every prop on desktop, tablet or phone.
Install
npm install --save rotating-textUsage
text updates the content, ignoring spaces.
stagger gives you control over the time between each letter.
timing sets the duration of each letter animation. Timing can be a single numeric value OR a custom timing array, with a specific duration for each letter in the text (e.g. if text is OKAY, your custom timing array can look like [0.1, 0.4, 0.5, 0.1]).
You can use className and style to add further customization and styling.
import React from 'react'
import { RotatingText } from 'rotating-text'
import 'rotating-text/dist/index.css'
function MyApp() {
return (
<RotatingText
text='HOVERME'
stagger={0.1}
timing={0.5}
className='rotating-text'
style={{ fontSize: '100px' }}
/>
)
}Props
| Prop | Type | Default | Description |
| ----------- | --------------------- | ----------- | ------------------------------------------------------------------------- |
| text | string | (required) | Text to animate. |
| stagger | number | 0.1 | Seconds between each letter starting its animation. |
| timing | number \| number[] | 0.5 | Seconds each letter's animation lasts, or one duration per letter. |
| variant | 'roll' \| 'flap' | 'roll' | roll turns each letter over like a cube; flap draws split-flap tiles. |
| className | string | undefined | Class name added to the outer container. |
| style | React.CSSProperties | undefined | Inline styles applied to the outer container. |
When text changes on the roll, each letter that changed turns over to the new one, in the same stagger and spring as a hover, and so does any letter a wider or narrower one pushes along; letters added or removed turn in from blank or out to blank. The width eases to the new word's over the first letter's timing, so text beside it glides along instead of jumping. A shorter word keeps the old one's room until its letters have turned away. With reduced motion on the text changes at once.
Screen readers, selection and copying get the new text as soon as text changes, as one word, from an unseen copy of the text under the turning letters. A selection's highlight is drawn behind the letters in the usual colour, or a page's own ::selection background; --rt-selection sets it for the roll alone.
Split-flap tiles
variant="flap" draws every letter on its own tile, split by a seam. On hover or tap the top half of each tile falls over the seam and bounces to rest, like a departures board. When text changes, each tile flips from its old letter to its new one, so a board can count, cycle words or follow typing; tiles added or removed flip in from blank or out to blank. A space becomes a blank tile, so padding the text to one length (word.padEnd(6)) keeps a board the same number of tiles, like a real one. With reduced motion on, letters change in place without flipping.
The tiles are styled with CSS custom properties, set on className or style:
| Property | Default | Description |
| ------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --rt-tile | #1d1d1f | Tile background. |
| --rt-ink | inherited | Letter colour. |
| --rt-seam | #000 | Colour of the seam across the middle. |
| --rt-seam-width | max(1px, 0.012em) | Height of the seam. |
| --rt-gap | 0.08em | Space between tiles. |
| --rt-radius | 0.06em | Tile corner radius. |
| --rt-padding | 0.08em 0.1em | Space around each letter inside its tile. |
| --rt-tile-width | 0.62em | Minimum tile width. |
| --rt-widest | M and W | Letters every tile is at least as wide as (a CSS string, such as 'W'), so new text never resizes the board. Set none to fit tiles to the text itself when it never changes. |
| --rt-perspective | 3.5em | Depth of the flap's 3D fall. |
<RotatingText text='Departures' variant='flap' className='board' />.board {
font-size: 80px;
--rt-tile: #182139;
--rt-ink: #f1ece1;
}Notes
- Text wrapping is currently not supported. RotatingText works best with a single word or short phrase, as spaces are ignored (in the
flapvariant a space is a blank tile). - The text flips when the pointer moves onto it, which on a touch screen is a tap. A flip always runs to the end; hovering again mid-flip does nothing.
License
MIT © jueungrace
