Scramble Text
Decryption-style text animation — characters churn through random glyphs and lock in from left to right, triggered by viewport or hover.
npx shadcn@latest add https://webberui.com/r/scramble-text.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<ScrambleText />
Installation
npx shadcn@latest add https://webberui.com/r/scramble-text.jsonOr, once registries are configured in components.json, install it as @webberui/scramble-text.
Usage
import { ScrambleText } from "@/components/ui/scramble-text";
<ScrambleText
text="WEBBERUI DECRYPTED"
className="font-mono text-4xl font-bold"
/>Hover-to-replay mode, and mixed Chinese/English is no problem:
<ScrambleText text="Hover me: decryption animation" trigger="hover" duration={0.04} />A custom scramble character set (for example a hacker-style 0 and 1):
<ScrambleText text="BINARY MODE" charset="01" className="font-mono" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | — | The target text; Chinese and emoji are both fine |
duration | number | 0.05 | Interval at which each character locks in (seconds); smaller decrypts faster |
charset | string | alphanumerics + symbols | The character set used for the scramble churn |
trigger | "view" | "hover" | "view" | Play automatically on entering the viewport, or replay on mouse hover |
once | boolean | true | With trigger="view", plays only the first time the element enters the viewport |
How it works
- At its core is a single
requestAnimationFrameloop: it computes how many characters have locked in from the elapsed time (one more character locks from the left everydurationseconds), and every 2 frames the unlocked positions draw a new random glyph fromcharset, so the per-frame flicker is not too harsh. The animation writes straight into the DOM text node and does not trigger a React re-render; the previous rAF is cancelled on unmount and on replay - Grapheme splitting uses
Intl.Segmenter, so Chinese characters, emoji, and combining characters each count as one unit. Locking in restores the original character directly, so Chinese target text works exactly the same, while the scramble churn always usescharset - Whitespace does not scramble, keeping line width and line breaking stable throughout the animation
- Character width jitter: scrambled glyphs have different widths, so the layout jumps sideways. Pairing with
font-mono(a monospaced font) is recommended, or at leasttabular-numsin mostly numeric scenarios. When the target text contains Chinese, the width difference between Chinese and Latin makes the jitter more obvious, and a monospaced font works best - Accessibility: the complete text lives in an
sr-onlyelement and the animation layer is markedaria-hidden, so the screen reader always reads a complete sentence instead of scrambled glyphs; when the user has "reduce motion" enabled at the system level, the final text is shown directly with no animation - With
once={false}andtrigger="view", leaving and re-entering the viewport replays the animation; withtrigger="hover"the text is shown statically and decrypts again on every mouse enter
Rolling Number
Odometer-style number wheels — when value changes, each digit springs vertically to its new value; added digits fade in and removed digits collapse.
Text Morph
A smooth morphing transition between two strings — shared characters slide to their new positions while the rest fade out and in, with auto-rotation and controlled switching.