Skip to content

Text Rotator

One line of text at a time: the next one moves up to take its place every few seconds.

$npx shadcn@latest add https://framebrick.co/r/text-rotator.json

From the Marai Neesu template, see it in context.

Hi, I'm Alex Rivera

Product Designer, Web Designer, Solopreneur, Digital Creator

Installation

$ npx shadcn@latest add https://framebrick.co/r/text-rotator.json

Usage

import { TextRotator } from "@/components/ui/text-rotator";

<p className="text-2xl font-semibold">
  I am a <TextRotator items={["Product Designer", "Web Designer", "Solopreneur"]} />
</p>

Props

PropTypeDefaultDescription
itemsstring[]—The texts, in order. With fewer than two nothing moves.
intervalnumber4000Milliseconds each text stays; not less than 1400, the time a move takes.
gapnumber10Space between two texts in the column, in px. It only shows during a move.
classNamestring—Classes for the window: the text size and weight go here.
  • It sizes itself from the text: the window is one line tall (1lh, the line height it inherits) and as wide as the widest text, so the words around it never move. It needs the lh unit: Chrome 109, Safari 16.4 or Firefox 120.
  • A CSS transition on Framer's slideshow spring (stiffness 200, damping 40, mass 1: over-damped, no overshoot) as a linear() curve within 2% of it, over 1121 ms. No animation library, and the first text is in the server HTML.
  • Forever: a copy of the first text waits under the last, and when the move reaches it the column jumps back to the start with no transition, which nobody can see.
  • Reduced motion: it keeps changing, as Marai Neesu's does, but each step is a jump. It waits while the tab is hidden or the rotator is scrolled out of view.
  • All the texts are in the markup once, visually hidden, for assistive technology; the moving copy is aria-hidden, so nothing is read twice and nothing is announced as it changes.

AI prompt

Paste into v0, Lovable, Bolt or Claude to rebuild this component in your own project.

Create a React + Tailwind CSS component called TextRotator — a client component, no animation library.
- Props: items (string[]), interval (ms, default 4000, not less than 1400), gap (px, default 10), className.
- A root span: relative inline-block, height 1lh (the line height it inherits), overflow-hidden, align-bottom. Inside it a visually hidden span (sr-only) with the items joined by ", ", and an aria-hidden flex-col column of the items plus a copy of the first one at the end, each item block, height 1lh, whitespace-nowrap, the column's gap in px.
- Every interval the column moves one step up: transform translateY(calc(index * -1 * (1lh + gap))), with a CSS transition on transform of 1121ms on a spring (stiffness 200, damping 40, mass 1) written as a linear() curve, cubic-bezier(0.22, 1, 0.36, 1) as the fallback. Reduced motion: no transition, so each step is a jump; it keeps going.
- When the index reaches the copy of the first item, wait 1121ms (0 with reduced motion), switch the transition off, set the index to 0, and switch it on again two animation frames later: a seamless loop.
- Pause while the tab is hidden (visibilitychange) or the rotator is out of view (IntersectionObserver). The first item must be in the server HTML.

Be the first to know

Get new templates and components first

One short email when we release a template or a free component. No spam — unsubscribe anytime.

We use your email only for Framebrick updates. Privacy policy