---
title: "How to Create Rotating (Cycling) Text in Framer"
description: "Build rotating, cycling text in Framer — the native variant approach, a code override with real transitions, and a drop-in component option."
canonical_url: "https://framerhub.io/blog/rotating-text-framer"
last_updated: "2027-01-08T00:00:00.000Z"
---

Rotating text — one word in a headline that cycles between several options while the rest of the sentence stays put — is one of the most reused patterns in modern web design, and for good reason: it lets a single headline speak to several audiences or use cases without cluttering the page with five separate sentences. Here's how to build it properly in Framer, including the layout-jump problem that trips up most first attempts.

## The Two Failure Modes of Rotating Text

Almost every broken rotating text implementation fails in one of two ways:

1. **Layout jump.** When "websites" rotates to "apps" and the surrounding text visibly shifts left because the container resized to fit the new word, the effect looks glitchy instead of smooth.
2. **Abrupt cuts instead of transitions.** Text that hard-swaps with no animation at all reads as a bug, not a feature — the whole point of the effect is the motion between states, not just the end states themselves.

Both are fixable, and both come down to sizing the container correctly and choosing a transition that suits how text — specifically — should move, which is different from how a generic UI element should move. Text needs a slightly different animation vocabulary than buttons or images: a hard scale or a bounce that reads as playful on a button often reads as unstable on a word inside a sentence someone is trying to read, so the safest transitions for text are the ones that preserve legibility throughout the motion rather than distorting the letterforms.

If you've worked through our broader [Framer animations and hover effects guide](/blog/framer-animations-hover-effects), the same principles apply here — the difference is that rotating text has one extra constraint hover effects don't: the surrounding sentence has to keep reading correctly no matter which word is currently showing.

## Native Framer: What's Possible Without Code

Framer's component variants can cycle between states on a timer using the "After delay" trigger chained between variants, which technically produces rotating text. The problem is coordination: you're managing a chain of manual transitions, one per word, and every time you add or reorder a word in the list you're rebuilding the variant chain by hand. It works for a fixed 3-word rotation you'll never touch again; it becomes tedious fast for anything you expect to iterate on. For most projects, a small code override ends up being less total effort than maintaining a growing variant chain.

## Building It With a Code Override

This implementation cycles through a word list with a vertical slide-and-fade transition, using `motion/react`'s `AnimatePresence` to handle the exit animation cleanly — the detail most hand-rolled CSS versions get wrong.

```jsx
import { useState, useEffect } from "react"
import { motion, AnimatePresence } from "motion/react"
import { addPropertyControls, ControlType } from "framer"

export default function RotatingText(props) {
  const { words, interval, textColor, fontSize } = props
  const list = words && words.length ? words : ["websites", "apps", "brands"]
  const [index, setIndex] = useState(0)

  useEffect(() => {
    const id = setInterval(() => {
      setIndex((i) => (i + 1) % list.length)
    }, interval * 1000)
    return () => clearInterval(id)
  }, [list.length, interval])

  return (
    <span
      style={{
        display: "inline-block",
        position: "relative",
        overflow: "hidden",
        verticalAlign: "bottom",
        height: `${fontSize * 1.2}px`,
      }}
    >
      <AnimatePresence mode="wait">
        <motion.span
          key={list[index]}
          initial={{ y: 24, opacity: 0 }}
          animate={{ y: 0, opacity: 1 }}
          exit={{ y: -24, opacity: 0 }}
          transition={{ duration: 0.35, ease: "easeInOut" }}
          style={{
            display: "inline-block",
            color: textColor,
            fontSize,
            fontWeight: "inherit",
          }}
        >
          {list[index]}
        </motion.span>
      </AnimatePresence>
    </span>
  )
}

addPropertyControls(RotatingText, {
  words: { type: ControlType.Array, control: { type: ControlType.String }, defaultValue: ["websites", "apps", "brands"] },
  interval: { type: ControlType.Number, defaultValue: 2.5, min: 1, max: 6, step: 0.5 },
  textColor: { type: ControlType.Color, defaultValue: "#000000" },
  fontSize: { type: ControlType.Number, defaultValue: 48, min: 12, max: 120 },
})
```

Drop this in as a code component and place it inline within your headline text layer — set its `fontSize` to match the surrounding headline exactly so the rotating word doesn't look mismatched in weight or size from the static text around it.

### Fixing the Layout Jump

The snippet above uses `AnimatePresence` with `mode="wait"`, which prevents the old and new word from being on screen simultaneously — that alone solves half the jump problem. The other half is horizontal width: if "brands" is much shorter than "websites," the text after it (if any) will visibly shift left as the word changes. The fix is either designing the sentence so the rotating word is the last word (nothing after it to shift), or giving the rotating word's wrapper a fixed `min-width` sized to your longest word so shorter words don't cause a reflow.

## Tuning the Transition Style

The vertical slide-and-fade above is the safest default, but a few variations suit different brand tones:

<table>
<thead>
  <tr>
    <th>
      Style
    </th>
    
    <th>
      Feel
    </th>
    
    <th>
      Best for
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Vertical slide + fade
    </td>
    
    <td>
      Clean, modern, safe default
    </td>
    
    <td>
      Most SaaS and agency headlines
    </td>
  </tr>
  
  <tr>
    <td>
      Fade only (no movement)
    </td>
    
    <td>
      Calm, understated
    </td>
    
    <td>
      Editorial or minimal brand sites
    </td>
  </tr>
  
  <tr>
    <td>
      Blur-to-sharp
    </td>
    
    <td>
      Techy, slightly dramatic
    </td>
    
    <td>
      Product/AI-forward brands
    </td>
  </tr>
  
  <tr>
    <td>
      Letter-by-letter reveal
    </td>
    
    <td>
      Playful, more elaborate
    </td>
    
    <td>
      Personality-driven brands, portfolios
    </td>
  </tr>
</tbody>
</table>

Swap the `initial`/`animate`/`exit` values in the snippet to change styles — for a blur-to-sharp version, animate `filter: "blur(8px)"` to `filter: "blur(0px)"` alongside the opacity change instead of the vertical `y` offset.

## Drop-In Option: The TextRotate Component

If you'd rather skip building and tuning the override yourself, FramerHub's [TextRotate component](/components/text-rotate) does this out of the box — word list, interval, transition style, and typography all exposed as property panel controls, with the layout-jump handling already solved. It's part of FramerHub's broader [component library](/components), so it drops into a project alongside any other components you're already using without a separate purchase flow. This is one of the more requested effects we've built — a straightforward hero pattern that shows up across an enormous range of niches, from SaaS landing pages to freelancer portfolios.

## Where Rotating Text Works Best

- **Hero headlines** describing what you do for multiple audiences: "We help <span>

founders / agencies / freelancers

</span>

 launch faster."
- **Value proposition lists** rotating through benefits: "Save <span>

time / money / headaches

</span>

."
- **Category or use-case rotation** on a product page: "Perfect for <span>

portfolios / SaaS / agencies

</span>

."

It works less well buried mid-paragraph in body copy, where the motion competes with reading rather than replacing a static headline choice — reserve it for short, prominent text, not sentences a visitor is meant to read start to finish at a normal reading pace.

We've actually tracked our own results with this pattern: an earlier version of this article family started ranking for "rotating text generator" without any dedicated targeting, which tells us there's real search demand from people looking for exactly this kind of practical, code-included walkthrough rather than a generic definition of what rotating text is. That's part of why this guide leans so heavily on working code and concrete tuning numbers instead of just describing the effect in the abstract.

## Combining Rotating Text With Other Hero Elements

Rotating text rarely appears alone — it's usually one element in a hero section that also includes a supporting subheadline, a CTA button, and often a visual element like an image or a background effect. A few pairing notes worth knowing before you build the full section:

- **Keep the CTA button static.** If both the headline and the button are animating on their own timers, the hero feels chaotic rather than alive. Let the rotating text be the one moving element and keep everything else calm around it.
- **Sync entrance timing.** If the whole hero fades in on page load, let that entrance finish before the rotation starts cycling — a word swap happening mid-entrance-animation looks like a rendering glitch rather than an intentional effect.
- **Watch total motion on the page.** If your hero background also has an animated gradient or particle effect running simultaneously, rotating text adds a third moving layer competing for attention — budget which single element gets to move continuously and keep the rest calm.

If you're assembling a full hero section and don't want to hand-build every piece, FramerHub's [component library](/components) has hero-ready pieces beyond just rotating text — buttons, backgrounds, and reveal effects that are built to pair well together rather than compete for attention.

## Accessibility Considerations

An infinitely looping animation can be genuinely distracting for visitors with attention-related sensitivities, and screen readers announcing every word change can turn a clean headline into a confusing stream of updates. Two practical fixes: cap the rotation to a fixed number of loops (3-4 full cycles) rather than running indefinitely, and use `aria-live="off"` or `aria-hidden="true"` on the rotating element combined with a visually hidden, static version of the full sentence for screen readers, so assistive technology gets one clean readout instead of a running commentary of every word swap.

It's also worth respecting `prefers-reduced-motion` here the same way you would for any other animated element — a rotating headline that instead just displays the first word statically for motion-sensitive visitors loses nothing important about the message, since the words are meant to be roughly interchangeable options rather than a sequence that needs to be seen in full to make sense.

## Common Mistakes to Avoid

A handful of small missteps show up repeatedly in rotating text implementations that are otherwise well-built:

- **Font weight or size mismatch between the rotating word and the static text.** If the code component's default styling doesn't exactly match your headline's typography, the rotating word visually stands out for the wrong reason. Always set the override's font properties to match the surrounding text precisely, rather than relying on default values.
- **Punctuation that doesn't work across every word.** "We build <span>

websites

</span>

." reads fine, but if one option in your list is a phrase rather than a single word ("custom web applications"), check that the sentence still reads naturally with every option substituted in, not just the first one you tested.
- **Starting the rotation before the page has settled.** If the rotation begins immediately on mount before layout has stabilized (fonts loading, images resizing), the first cycle or two can visibly jump. A brief initial delay (200-300ms) before the interval starts avoids this.
- **Testing with only short placeholder words.** "One / two / three" all behave identically in testing but hide layout-jump issues that only appear with your real, differently-sized word list. Always test tuning decisions with the actual production copy.

## FAQ

**What is rotating text used for on a website?**
Most commonly in a hero headline, where one word or phrase cycles through several options to show range — "We build <span>

websites / apps / brands

</span>

 that convert" — without needing a separate headline for every audience or use case.

**Can I make rotating text in Framer without any code?**
You can fake a basic version with a variant cycle tied to a delayed transition loop, but it's fragile and hard to keep in sync across multiple words with different lengths. A short code override gives you a cleaner, more reliable result with less setup effort overall.

**How do I stop text from jumping around as the words change length?**
Set a fixed minimum width on the rotating word's container based on your longest word, or use a monospace-adjacent sizing strategy, so shorter words don't cause the surrounding layout to visibly reflow on every cycle.

**What's a good rotation speed?**
2 to 3 seconds per word is the sweet spot for most headlines — long enough to read comfortably, short enough that visitors don't lose patience waiting for the next word. Faster than 1.5 seconds starts to feel frantic; slower than 4 seconds starts to feel like the page is stuck.

**Should rotating text ever stop?**
For accessibility and to avoid distracting a visitor who's trying to read the rest of the page, many implementations cap the cycle after 3-4 loops through the full word list and settle on the final word, rather than animating indefinitely for as long as the visitor stays on the page.
