Rolling Text <mv-rolling-text>

Hover-Beschriftung, die Buchstabe für Buchstabe von links nach rechts nach oben rollt und wieder landet oder ein zweites Label von unten landen lässt, mit leichter Unschärfe im Übergang und einer Grundfläche, die auf das längere Label festgelegt ist; Variante glide: Eine Markierung gleitet zwischen den Satzteilen eines Satzes. Der echte Text bleibt ein einziger schlichter, auswählbarer, übersetzbarer Textknoten.

KategorieAnimierter Text
TypWeb Component (<mv-rolling-text>)
Statusstabil
Keywordstext, roll, slot, cascade, hover, letters, stagger, blur, label-swap, highlight, marker, glide, nav, button, accessible

When to use

  • Nav links or buttons should roll their label on hover or keyboard focus without any layout shift
  • A call to action should swap in a short second label, like Start writing to It’s free
  • A marker should glide between key phrases of a sentence on hover or on its own
  • A sold or public page needs hover text that stays selectable, findable and translatable

Avoid when

  • A 3D cube flip per letter or a single roll on view or load is wanted → use Letter Swap instead
  • The swapped label carries needed information; screen readers never get it and touch never reveals it

Installation

node scripts/add.mjs rolling-text --out ./src/marvelous

KI-Agent mit dem MCP-Server von Marvelous UI: install_components({ slugs: ["rolling-text"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Kopierte Dateien (inklusive Abhängigkeiten): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/rolling-text/rolling-text.js, components/rolling-text/rolling-text.css.

Verwendung

Schnellstart mit dem kleinsten funktionierenden Markup:

<a href="/work"><mv-rolling-text hover-text="View all">Work</mv-rolling-text></a>

Referenz-Markup zum Starten und Anpassen mit Attributen, data-* und CSS-Variablen:

<div style="display:grid;gap:2.5rem;width:100%;max-width:44rem">
  <nav aria-label="Main" style="display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem;padding:.625rem .75rem .625rem 1.25rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-full);background:var(--mv-surface);box-shadow:var(--mv-shadow-sm)">
    <strong style="font-size:.9375rem;letter-spacing:-.01em">Fieldnote</strong>
    <ul style="display:flex;gap:1.5rem;margin:0;padding:0;list-style:none;font-size:.875rem;font-weight:500">
      <li><a href="#product" style="color:inherit;text-decoration:none"><mv-rolling-text>Product</mv-rolling-text></a></li>
      <li><a href="#customers" style="color:inherit;text-decoration:none"><mv-rolling-text hover-text="Stories">Customers</mv-rolling-text></a></li>
      <li><a href="#pricing" style="color:inherit;text-decoration:none"><mv-rolling-text hover-text="From $12">Pricing</mv-rolling-text></a></li>
    </ul>
    <a href="#signup" class="mv-button" data-variant="primary" style="border-radius:var(--mv-radius-full)"><mv-rolling-text hover-text="It’s free →" style="--mv-rolling-text-align:center">Start writing</mv-rolling-text></a>
  </nav>

  <a href="#changelog" style="justify-self:start;color:inherit;text-decoration:none;font-size:clamp(2.25rem,6vw,3.5rem);font-weight:650;letter-spacing:-.035em;line-height:1">
    <mv-rolling-text hover-text="Read the changelog" stagger="22" style="--mv-rolling-text-leading:1.08">What’s new in 4.0</mv-rolling-text>
  </a>

  <mv-rolling-text variant="glide" autoplay="2600" style="font-size:clamp(1.25rem,3vw,1.625rem);line-height:1.45;letter-spacing:-.015em;color:var(--mv-fg-muted);max-width:36rem">
    Fieldnote keeps <mark>every draft in sync</mark>, turns meetings into <mark>searchable notes</mark> and ships <mark>offline by default</mark>, so your team can <mark>write from anywhere</mark>.
  </mv-rolling-text>
</div>

API

Attributes

NameTypDefaultDescription
variantroll | gliderollroll: rolling letters; glide: a marker gliding between <mark> elements.
hover-textstringroll: label that lands on hover (the same text otherwise). The width is that of the longer label from the start.
triggerhover | manualhoverhover follows the parent link / button (mouse or pen hover and keyboard focus, never touch); manual: driven by active.
activebooleanForces the rolled state.
staggernumber28Delay between letters (ms).
durationnumber520Duration per letter (ms).
autoplayboolean | numberglide: the marker moves to the next phrase on its own (ms, 2800 by default, 800 minimum), paused on hover, focus, off-screen, in hidden tabs and with reduced motion.

Properties

NameTypDescription
indexnumberglide: highlighted phrase.

Methods

NameDescription
select(index)glide: highlights a phrase and makes it the resting position.

Events

NameDescription
mv-changeglide: the marker moved to another phrase. detail: { index, phrase }.

Content structure

NameDescription
<mark> / [data-phrase]glide: highlightable phrases (data-active = starting phrase). Links inside stay focusable and move the marker.

CSS classes

NameDescription
mv-rolling-text-textroll: wrapper of the real text (your original nodes, unchanged).
mv-rolling-text-stage / -line / -charroll: generated aria-hidden letter stage, shown only while rolling or while a different label is up.
mv-rolling-text-marker / -phraseglide: marker pieces (one per line of a wrapped phrase) and phrases.

CSS variables

NameDefaultDescription
--mv-rolling-text-leading1.2Line height, which is also the height of the rolling window.
--mv-rolling-text-easingcubic-bezier(0.7, 0, 0.2, 1)Roll easing curve.
--mv-rolling-text-blur3pxBlur of letters in transit.
--mv-rolling-text-alignstartAlignment when the two labels differ in length (start, center, end).
--mv-rolling-text-markeraccent 22%glide: marker background.
--mv-rolling-text-marker-radius0.3emglide: marker corner radius.
--mv-rolling-text-active-fgvar(--mv-fg)glide: color of the highlighted phrase.

Accessibility

roll: your text stays a plain, visible text node inside the element, so screen readers, the parent’s accessible name, selection, find-in-page and page translation get it unchanged. While rolling it is only made transparent and the letters are painted as generated content on an aria-hidden, non-selectable stage placed on the measured position of each letter, so nothing jumps when the roll starts or ends. The second label is decorative: the accessible name stays the original text. Hover follows the parent’s keyboard focus (:focus-visible) and ignores touch. With reduced motion (system or data-motion="reduce") the text never moves: without hover-text nothing happens, with it the label swaps instantly. Printing shows the real text. glide: <mark> elements keep their semantics and links inside stay focusable; the marker is aria-hidden and becomes a Highlight outline in forced colors; autoplay stops with reduced motion, off-screen and in hidden tabs.

Diese Seite wurde mit KI übersetzt. Übersetzungsfehler melden