Exclusivobeta
Wind Text <mv-wind-text>
Texto cujas letras se comportam como grama (ou uma bandeira) num único campo de vento compartilhado por toda a página: a rolagem envia rajadas cuja frente varre o texto no sentido da rolagem, o cursor sopra localmente numa grade de velocidades advectada que se dissipa, cada letra se curva sobre a linha de base com a própria mola e alguns grãos de pólen levantam voo onde o vento sopra.
| Categoria | Texto animado |
|---|---|
| Tipo | Web Component (<mv-wind-text>) |
| Status | beta |
| Keywords | exclusive, wind, text, typography, scroll, cursor, spring, fluid, particles, pollen, editorial, headline |
When to use
- An editorial headline should sway like grass or a flag in response to scroll and cursor
- An organic or nature brand wants a gentle ambient breeze with drifting pollen
Avoid when
- The text contains links or buttons; they are flattened to plain text
- Long paragraphs at full strength; swaying letters hurt reading, so keep strength low or skip it
Instalação
node scripts/add.mjs wind-text --out ./src/marvelousAgente de IA com o servidor MCP do Marvelous UI: install_components({ slugs: ["wind-text"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Arquivos copiados (dependências incluídas): tokens/tokens.css, core/base.css, core/canvas.js, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/wind-text/wind-text.js, components/wind-text/wind-text.css.
Uso
Marcação de referência, para usar como ponto de partida e personalizar com atributos, data-* e variáveis CSS:
<section id="wind-demo" class="wt-hero" lang="en">
<style>
.wt-hero { position: relative; overflow: hidden; width: min(100%, 64rem); margin-inline: auto; padding: clamp(2rem, 1rem + 5vw, 4.5rem) clamp(1.25rem, 1rem + 4vw, 4rem) 3rem; border-radius: var(--mv-radius-2xl); border: 1px solid var(--mv-border);
background:
radial-gradient(120% 70% at 85% 110%, color-mix(in oklch, var(--mv-success) 16%, transparent), transparent 60%),
radial-gradient(90% 60% at 0% 0%, color-mix(in oklch, var(--mv-warning) 12%, transparent), transparent 65%),
var(--mv-surface);
font-family: var(--mv-font-sans); }
.wt-kicker { margin: 0 0 1.25rem; display: flex; gap: .625rem; align-items: center; font-size: var(--mv-text-xs); letter-spacing: .14em; text-transform: uppercase; color: var(--mv-fg-muted); font-weight: var(--mv-weight-semibold); }
.wt-kicker::before { content: ""; width: 1.75rem; height: 1px; background: currentColor; opacity: .6; }
.wt-title { margin: 0; max-width: 15ch; font-size: clamp(2.75rem, 1.5rem + 5.2vw, 5.25rem); line-height: 1.02; letter-spacing: -0.035em; font-weight: 800; color: var(--mv-fg); text-wrap: balance; }
.wt-title em { font-style: normal; color: color-mix(in oklch, var(--mv-success) 78%, var(--mv-fg)); }
.wt-lede { margin: 1.5rem 0 0; max-width: 40rem; font-size: var(--mv-text-lg); line-height: 1.6; color: var(--mv-fg-muted); }
.wt-actions { margin-top: 2rem; display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }
.wt-hint { margin-left: auto; font-size: var(--mv-text-xs); color: var(--mv-fg-subtle); }
.wt-meadow { position: absolute; inset: auto 0 0 0; height: 5rem; pointer-events: none; opacity: .5;
background: repeating-linear-gradient(90deg, color-mix(in oklch, var(--mv-success) 30%, transparent) 0 1px, transparent 1px 9px);
mask-image: linear-gradient(to top, #000, transparent); }
</style>
<p class="wt-kicker">Highland Seed Co. · Spring 2026 catalog</p>
<h2 class="wt-title"><mv-wind-text strength="1.25" pollen="26">Sow to every <em>wind.</em></mv-wind-text></h2>
<p class="wt-lede"><mv-wind-text strength="0.55" pollen="8">Open-pollinated heirloom seeds, grown without chemicals in the Vermont hills. Every packet saves an old variety from oblivion: Brandywine tomato, scarlet runner bean, bearded Red Fife wheat.</mv-wind-text></p>
<div class="wt-actions">
<a class="mv-button" href="#wind-demo">Browse the catalog</a>
<button class="mv-button" data-variant="outline" type="button" data-gust>Make it blow</button>
<span class="wt-hint">Move your mouse or scroll</span>
</div>
<div class="wt-meadow" aria-hidden="true"></div>
</section>
<script type="module">
const root = document.getElementById("wind-demo");
const { gust } = await customElements.whenDefined("mv-wind-text");
let dir = 1;
root.querySelector("[data-gust]").addEventListener("click", () => { gust(1.3, dir); dir = -dir; });
// A first gust on arrival so the idea reads instantly.
setTimeout(() => gust(1.1, 1), 350);
</script>API
Attributes
| Name | Tipo | Default | Description |
|---|---|---|---|
variant | grass | flag | grass | grass: each letter bends and sways around its base; flag: a wave runs along the line like a pennant. |
strength | number | 1 | Letter flexibility (0 to 3): 0.5 for a paragraph, 1.2 for a big headline. |
pollen | number | 18 | Maximum number of pollen/dust grains in flight (0 = none). |
breeze | number | 0 | Constant ambient breeze (0 to 1). Above 0, the animation runs as long as the text is visible. |
Methods
| Name | Description |
|---|---|
gust(strength = 1, direction = 1) | Sends a gust across every instance (direction 1 → right, −1 → left). Also available as a static: MvWindText.gust(). |
Content structure
| Name | Description |
|---|---|
(text) | Plain text; inline tags (em, strong, span) are kept visually, links and buttons are flattened to text. |
CSS classes
| Name | Description |
|---|---|
mv-wind-text-word / -char | Generated words (non-breaking) and letters; letters pivot near the baseline (transform-origin 50% 84%). |
mv-wind-text-canvas | Pollen canvas, overflowing by 64 px. |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-wind-text-pollen | var(--mv-warning) | Pollen grain color. |
Accessibility
The text is exposed only once, through a visually hidden copy; the animated letters and the canvas are aria-hidden, purely decorative, with no interaction required. One wind field, one loop and passive listeners for the whole page; the loop stops as soon as the air is calm and the letters are upright, and only computes visible instances. On touch devices, only scrolling blows. Reduced motion: no animation, letters stay still and perfectly readable.