shadcn.io is not affiliated with official shadcn/ui
Iris Text reveals a line a letter at a time, each letter seen through a circle that opens from its centre, like a camera's aperture, until the whole of it shows. The letters never move: they're in place from the first frame, and only what you see of them grows. It plays once, when the text scrolls into view.
Use it for a heading, a product name or a title card with a precise, photographic feel. For letters that slide into place, use Splitting Text; for letters that come into focus from a blur, Blur Text; for letters that unfold, Paper Fold Text. Each letter is clipped by a circle that a CSS keyframe animation opens, delayed by its place in the line, with no animation library; once a letter is open the clip is gone. With reduced motion the text is simply there.
Installation
Usage
import { IrisText } from "@/components/ui/iris-text";<h2>
<IrisText text="Picture perfect" />
</h2>Demos
Words
by="words" opens each word through one circle, 180 ms apart: for a longer line, and for scripts whose letters join, such as Arabic, which a split between letters would break.
Timing
duration is how long one letter takes to open, 600 ms by default, and stagger the time between one letter and the next, 60 ms. Short ones suit a small label; long ones, a title revealed slowly.
Accessibility
Screen readers read the whole text once, as plain text: the opening letters are hidden from them, and a visually hidden copy carries it. Words wrap whole, and the line keeps its direction on a right-to-left page. With reduced motion every letter is open from the start.
FAQ
When does the animation play?
Once, when at least a quarter of the text is in view: an IntersectionObserver on the text starts it, then stops watching. Pass trigger="mount" to play it as soon as the page shows it, for text that's always on screen.
Does the circle cut off parts of letters?
No. It opens to just past the corners of each letter's box, then the clip is removed altogether, so accents, descenders and the overhang of an italic show whole once a letter is open.
Does the line move while it opens?
No. Each letter is in its place from the start and only its clip changes, so nothing around the text shifts.
What if JavaScript is off or slow to load?
With trigger="view", the server renders the letters closed, waiting, and a page without JavaScript shows the text at once. With trigger="mount" the animation runs from CSS alone, before the page's script loads.
API Reference
IrisText
<span> data-slot="iris-text"
textstring
The text.
by?"characters" | "words"
What opens on its own: each character, or each word (for scripts whose letters join, such as Arabic).
- Type
"characters" | "words"- Default
"characters"
duration?number
How long one character or word takes to open, in milliseconds. @default 600.
onComplete?() → void
Called once the last character or word is open.
- Returns
void
stagger?number
The time between one character or word and the next, in milliseconds.
- Default
60 (characters), 180 (words)
trigger?"mount" | "view"
When it plays: as soon as it's on the page, or once it scrolls into view.
- Type
"mount" | "view"- Default
"view"
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
data-last?stringdata-view?string
"in" when visible is true, otherwise "out".
--iris-text-durationstring
One unit's opening.
Related
Splitting Text
EntranceLetters that slide into place
Blur Text
EntranceWords that come into focus from a blur
- Pro
Paper Fold Text
EntranceLetters that unfold from the middle
- Pro
Mask Reveal Text
EntranceA panel wipe across the whole line
- Pro
True Focus
InteractiveA camera pulling focus word by word
- Pro
Xray Text
InteractiveA round hole that shows a second text