Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Shatter Text for React

Text that shatters like glass when it's clicked and springs back together on the next click. For React with Base UI, when a headline should break on impact.

Framework

Shatter Text breaks like glass. Click it and every character cracks into five sharp pieces that fly apart, turning and fading, and hang there in the air; click again and they spring back together into the text, overshooting a hair before they settle.

Use it for a 404 page, an easter egg, a "do not press" moment or a word that should feel fragile. For letters that fall and pile up instead, use Gravity Text; for a digital glitch, Glitch Text. At rest each character is itself, whole; shattered, it's five copies, each clipped to a wedge, and CSS transitions the install adds to your stylesheet carry them out to places worked out from the character's place in the text, then back on a spring: no animation library and no frame loop. With reduced motion the pieces don't fly: the text just cracks, and mends.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { ShatterText } from "@/components/ui/shatter-text";
<h1>
  <ShatterText text="Shatter" />
</h1>

Demos

Intensity

intensity is how far the pieces fly: subtle keeps them close around the word, strong scatters them wide. Click each to see. duration is the flight apart, 700 ms by default; coming back together takes a fifth longer.

Preview width

Controlled

shattered holds the state yourself: here a button beside the text breaks it and mends it. trigger="manual" leaves the text itself unclickable, for text inside your own button or link, and onShatteredChange reports each change a click makes.

Preview width

Accessibility

Screen readers always hear the text whole: the pieces are hidden from them, and the text is read once, as the name of a real button laid over it, with aria-pressed saying whether it's shattered. Tab reaches it, and Enter or Space shatters it or mends it, like a click. With trigger="manual" there's no button, just the text, read once. With reduced motion nothing flies: the pieces sit a hair apart, a cracked word, and mend at once.

Tab
Move focus to the text.
Enter
Shatter the text, or put it back together.
Space
Shatter the text, or put it back together.

FAQ

How is a character cut into pieces?

Each character has five copies of itself, each clipped with clip-path to a wedge from a point a little below its middle, cut past its box so no stroke is lost. At rest only one whole copy shows, so no seams run through the text; the pieces take over the moment it shatters and hand back once they've landed.

Is the pattern random?

It looks random but isn't: where every piece flies, how far it turns and how faint it gets come from its character's place in the text by a small formula, so the pattern is the same on every load and on the server, and different for every letter.

Can I shatter a whole paragraph?

It's made for a headline or a short label: every character is six elements, so a long paragraph means a lot of pieces. Shatter the line that matters and leave the rest still.

Can I use it inside a button?

Yes, with trigger="manual", which renders no button of its own, and shattered driven by your button. Keep the label readable for whoever presses it next, for example by mending it after a moment.

How do I make the pieces fly further than strong?

intensity sets --shatter-text-spread (0.55, 1 or 1.6); set the variable yourself, such as [--shatter-text-spread:2.5] on the text, for any other reach.

What happens with reduced motion?

A click still shatters and mends the text, but nothing flies or turns: the pieces sit about a twentieth of an em apart, a cracked word, and mend at once.

API Reference

ShatterText

<span> data-slot="shatter-text"

PropType
shattered?boolean

Whether the text lies in pieces, to hold that state yourself.

defaultShattered?boolean

Whether it starts shattered, when it keeps its own state. @default false.

Default
false
onShatteredChange?(shattered: boolean) → void

Called with the new state each time it shatters or comes back together.

Parameters

shattered – boolean

Returns
void
textstring

The text.

duration?number

How long the pieces take to fly apart, in milliseconds; coming back together takes a little longer.

Default
700
intensity?"subtle" | "medium" | "strong"

How far the pieces fly. @default "medium".

Type
"subtle" | "medium" | "strong"
trigger?"click" | "manual"

What shatters it: a click on it (a real button, which puts it back together too), or only shattered, for text inside your own button or link.

Type
"click" | "manual"
Default
"click"
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.

AttributeType
data-state?string

"shattered" when shown is true, otherwise "whole".

CSS variableType
--shatter-text-durationstring

The pieces' flight apart (700ms; coming back takes a fifth longer).

--shatter-text-spreadstring

How far the pieces fly, as a share of their reach (1).

All 97 text effects