Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Container Text Flip for React

A word in a box that flips to the next, the box growing or shrinking to fit each one. For React with Base UI, when the changing word of a headline should stand out as a badge.

Framework

Container Text Flip sets one word of a headline in a box and flips it to the next, again and again: the outgoing word fades into a blur, the box grows or shrinks to the next word's width, and the new word comes into focus inside it letter by letter. It pauses while the pointer is over it.

Use it for the word of a hero line that should read like a badge or a key: what a product makes things, who it's for. For a word that changes without a box and holds its widest width, use Flip Words or Rotating Text. A small timer counts the turns; at each one it reads the box's width and the next word's, laid out unseen, and a CSS transition runs between them, while CSS keyframe animations the install adds to your stylesheet bring the letters in, with no animation library. With reduced motion the words swap in place and the box simply fits each one.

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 { ContainerTextFlip } from "@/components/ui/container-text-flip";
<h2>
  Make your websites <ContainerTextFlip words={["better", "modern", "beautiful"]} />
</h2>

Demos

Colors

The box is the component itself, so its className styles it: a background, a border colour, a radius, a shadow. Here it takes the theme's primary colour; the letters keep the text colour you give it.

Preview width

Timing

duration is how long each word stays, 3000 ms by default, and stagger the time between one letter coming in and the next, 30 ms.

Preview width

Accessibility

Screen readers read every word once, as a list (better, modern, beautiful), from a visually hidden copy; the flipping letters are hidden from them, so they never hear a word change mid-sentence. The words stop while the pointer is over them, for anyone reading slowly, and with reduced motion they swap without blurring and the box changes size at once.

FAQ

How does the box know the next word's width?

The next word is always laid out, unseen and out of the way, inside the component. At each turn the timer reads the box's width and that word's, sets one and then the other, and a CSS transition on the width runs between them. Once it's done the box goes back to fitting its word on its own, so a font that loads late or a heading that changes size never leaves it the wrong width.

Does the text after it move?

Yes, as the box grows and shrinks, the way the box is meant to. Put it at the end of a line, as in a headline, and nothing moves at all; for a word that changes in the middle of a sentence without moving the rest, use Flip Words.

How do I change the box?

With className: bg-primary text-primary-foreground border-primary for a filled badge, rounded-full for a pill, shadow-none to drop its inner edge. The padding scales with the text, so the box fits a label as well as a hero line.

Does it pause?

Yes, while the pointer is over it, and it waits a full duration again once the pointer leaves. With a single word it never flips.

What do screen readers hear?

Every word once, separated by commas, in place of the box: "Make your websites better, modern, beautiful".

What happens with reduced motion?

The words still change, each replacing the last in place, and the box fits each new word at once, without blurring or resizing smoothly.

API Reference

ContainerTextFlip

<span> data-slot="container-text-flip"

PropType
wordsstring[]

The words, shown in turn from the first; a word may be a few words.

duration?number

How long each word stays, in milliseconds. @default 3000.

Default
3000
stagger?number

The time between one letter coming in and the next, in milliseconds. @default 30.

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-turn?string
CSS variableType
--container-text-flip-staggerstring

The time between one letter coming in and the next (30ms).

All 97 text effects