Word Rotate <mv-word-rotate>
用于 Hero 句子的行内轮换单词(滑动、3D 翻转、模糊或淡入淡出、逐字母),宽度平滑过渡,句子不会跳动。
工作原理
用于 Hero 句子的行内轮换单词(滑动、3D 翻转、模糊或淡入淡出、逐字母),宽度平滑过渡,句子不会跳动。默认即无障碍:屏幕阅读器听到的是一句列出所有选项的稳定句子,悬停或聚焦外层链接时停住,在屏幕外和隐藏的标签页中暂停,在减少动态效果模式下停留在一个单词上。
| 分类 | 动画文字 |
|---|---|
| 类型 | Web Component(<mv-word-rotate>) |
| 状态 | 稳定版 |
| Keywords | rotating-text, flip-words, text-loop, hero, headline, inline, layout-animation, accessible |
When to use
- A hero headline should cycle one inline word, like Build for designers, developers or teams
- The rotating word should sit in a tinted pill whose width animates between words
- A sold or public page needs a rotating word that screen readers hear once, not on every change
- The word loop must be driven from script with next, previous or an index
Avoid when
- A standalone word should melt into the next with a gooey blur → use Morphing Text instead
- Whole phrases should be typed and deleted letter by letter → use Typewriter instead
安装
node scripts/add.mjs word-rotate --out ./src/marvelous使用 Marvelous UI MCP 服务器的 AI 智能体:install_components({ slugs: ["word-rotate"], target_dir: "<absolute path>/src/marvelous", framework: "react" })。
复制的文件(含依赖):tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/word-rotate/word-rotate.js, components/word-rotate/word-rotate.css。
用法
快速开始,最小可运行标记:
<p>Build for <mv-word-rotate words="designers, developers, teams"></mv-word-rotate></p>标准标记,可在此基础上通过属性、data-* 和 CSS 变量进行定制:
<div style="display:grid;gap:2rem;width:min(100%,46rem);margin-inline:auto;text-align:center">
<h2 style="margin:0;font:700 clamp(1.9rem,4.6vw,3.2rem)/1.15 var(--mv-font-display);letter-spacing:-.035em">
Build for
<mv-word-rotate data-variant="pill" words="designers, developers, teams" style="--mv-word-rotate-color:var(--mv-accent-fg)"></mv-word-rotate>
<br>without the all-nighters.
</h2>
<div style="display:grid;gap:.9rem;font-size:clamp(1.1rem,2.4vw,1.45rem);font-weight:600;letter-spacing:-.02em">
<p style="margin:0">Interfaces that feel <mv-word-rotate effect="flip" interval="2200" words="fast, reliable, elegant, accessible" colors="var(--mv-accent), var(--mv-info), var(--mv-success), var(--mv-warning)"></mv-word-rotate></p>
<p style="margin:0">From prototype to <mv-word-rotate effect="blur" interval="2400" conjunction="and" words="production, launch, growth" style="--mv-word-rotate-color:var(--mv-accent)"></mv-word-rotate></p>
<p style="margin:0;color:var(--mv-fg-muted)">Ships as <mv-word-rotate effect="slide" direction="down" interval="1800" words="HTML, React, Vue, Svelte, Astro" style="--mv-word-rotate-color:var(--mv-fg);font-family:var(--mv-font-mono)"></mv-word-rotate>, zero friction.</p>
<p style="margin:0;color:var(--mv-fg-muted)">Looks <mv-word-rotate effect="fade" interval="2000" words="crisp, smooth, clean" style="--mv-word-rotate-color:var(--mv-fg)"></mv-word-rotate> by default.</p>
</div>
<p style="margin:0;font-size:.85rem;color:var(--mv-fg-muted)">Hover a word to hold it. Screen readers hear each sentence once, with every option.</p>
</div>API
Attributes
| Name | 类型 | Default | Description |
|---|---|---|---|
words | string | Words separated by commas (or |). Otherwise: one child per word. | |
effect | slide | flip | blur | fade | slide | Transition between two words; letters enter one after another. |
interval | number (ms) | 2600 | How long each word is shown. |
duration | number (ms) | 560 (680 for flip) | Duration of the transition and of the width glide. |
stagger | number (ms) | 18-30 (0 for fade) | Delay between letters. |
easing | CSS easing | var(--mv-ease-out) | Letter easing curve (tokens accepted). |
direction | up | down | up | Slide / flip direction. |
colors | list of CSS colors | One color per word, cycled. | |
conjunction | or | and | none | or | How the screen reader sentence joins the words: “designers, developers, or teams”. Uses the page language (lang). |
label | string | Replaces the screen reader sentence entirely. | |
paused | boolean | Pauses the rotation. It also holds by itself on hover, on focus of a wrapping link or button, off-screen and in hidden tabs. | |
data-variant | pill | Tinted pill whose width animates. | |
data-held | boolean | Set by the component while hover or focus holds the word (for styling). |
Properties
| Name | 类型 | Description |
|---|---|---|
index | number | Current word (settable, wraps around; assignable before the element is defined). |
Methods
| Name | Description |
|---|---|
next() | Next word. |
previous() | Previous word. |
Events
| Name | Description |
|---|---|
mv-change | New word shown (detail.index, detail.word). |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-word-rotate-color | inherit | Word color. |
--mv-word-rotate-duration | Default duration. | |
--mv-word-rotate-stagger | Default stagger. | |
--mv-word-rotate-easing | Letter easing curve. | |
--mv-word-rotate-width-easing | var(--mv-ease-emphasized) | Width glide easing curve. |
--mv-word-rotate-radius | 0.3em | Pill corner radius. |
Accessibility
The animated word is aria-hidden; a visually hidden sentence lists every option once (“designers, developers, or teams”, built with Intl.ListFormat in the page language), so screen readers never hear a change. There is no live region. The rotation holds while the pointer is on the word or while focus is inside a wrapping link or button, pauses off-screen and in hidden tabs, and under reduced motion shows one static word with no width animation. The pill keeps a visible outline in forced colors.