Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Spiral Text for React

Text wound into a spiral that turns slowly, each letter a little smaller than the last. For React with Base UI, when a cover, a label or a hero mark should draw the eye inward.

Framework

Spiral Text winds a line of text round and round towards a centre: each character a step further round, a little closer in and a little smaller than the one before, so the turns never collide and the text reads from the outside in. The whole spiral turns slowly, and the pointer over it can speed it up, slow it down or stop it.

Use it for a record label, a podcast cover, a badge or a hero mark, where a line of text is decoration first. For text set evenly around a ring, use Circular Text; for text that flows along any curve, Curved Loop. It's CSS only: each character's turn, distance and size are worked out from its place in the text by CSS maths the install adds to your stylesheet, and a keyframe animation turns the spiral, with no animation library. With reduced motion the spiral holds still.

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 { SpiralText } from "@/components/ui/spiral-text";
<SpiralText text="Round and round the words go, winding in towards the centre • " />

Demos

Turns

turns is how many times the text winds round, 2 by default. One turn makes a wide ring whose letters barely shrink; three make a tight coil that falls away quickly towards the centre. A short text winds fewer times than you ask, so its letters stay legible.

Preview width

Record

duration is one turn of the spiral, 30 seconds by default, and hover is what the pointer over it does: fast, the default, spins it four times as fast, slow halves its speed, pause stops it and none leaves it be. Here a quick label slows down under the pointer, so it can be read.

Preview width

Accessibility

Screen readers read the text once, in order, from a visually hidden copy, never the turned characters. The speed changes only with a pointer that hovers; on a touch screen the spiral turns at its own pace. With reduced motion it holds still, every character in its place.

FAQ

How big is the spiral?

As big as the text needs: the first character sits far enough out for the text to wind turns times, each character taking --spiral-text-spacing along the way. A longer text or a larger font makes a larger spiral, so set the font size to scale it.

Why do the letters get smaller towards the middle?

So the turns never crowd. Each character is turned, moved in and scaled down by the same small ratio as the one before, so the letters, the gaps between them and the room between turns all shrink together, and each turn sits just clear of the one outside it: the shape of a shell. It reads as a spiral even at its tightest.

How do I space the letters?

With --spiral-text-spacing, the room each character takes along the spiral, in em but unitless: 0.62 by default. Bold capitals want a little more, such as [--spiral-text-spacing:0.75]; the spiral grows to fit.

Why doesn't the spiral jump when the speed changes?

The extra speed is a second spin inside the spiral that only runs while the pointer is over it. Its turn adds to the spiral's (or takes from it, for slow), so the spiral carries on from where it is.

What about right-to-left text?

It winds the other way, anticlockwise from the outside in, so it still reads in order. Each character is placed on its own, so scripts whose letters join, such as Arabic, come apart: keep those on a straight line.

What happens with reduced motion?

The spiral holds still, with every character in its place.

API Reference

SpiralText

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

PropType
textstring

The text, from the outside in.

duration?number

One turn of the spiral, in milliseconds. @default 30000.

Default
30_000
hover?"fast" | "slow" | "pause" | "none"

What the pointer over the spiral does: spins it four times as fast, half as fast, stops it, or nothing.

Type
"fast" | "slow" | "pause" | "none"
Default
"fast"
turns?number

How many times the text winds round the centre; a short text winds fewer times, so its letters stay legible.

Default
2
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.

CSS variableType
--spiral-text-durationstring

One turn of the spiral (30s).

--spiral-text-spacingstring

The room each character takes along the spiral, in em, unitless (0.62).

All 97 text effects