beta
Particle Text <mv-particle-text>
Texto dibujado por miles de partículas en canvas muestreadas de la propia fuente del elemento: llegan a su sitio de izquierda a derecha, huyen del puntero y vuelven con un resorte, salen despedidas al hacer clic y fluyen hacia la nueva palabra cuando cambia el texto, coloreadas por un degradado que recorren.
| Categoría | Texto animado |
|---|---|
| Tipo | Web Component (<mv-particle-text>) |
| Estado | beta |
| Keywords | safe-rewrite, particles, canvas, text, morph, interactive, hero, repel |
When to use
- A hero title should be drawn by particles that assemble, flee the cursor and explode on click
- A short word should morph into another with particles flowing into place
Avoid when
- Low-end mobile or several instances per page; thousands of canvas particles are costly
- Long text or paragraphs; the canvas is built for a short word or title and shrinks overflowing text
- A changing number should be drawn in particles → use Particle Counter instead
Instalación
node scripts/add.mjs particle-text --out ./src/marvelousAgente de IA con el servidor MCP de Marvelous UI: install_components({ slugs: ["particle-text"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Archivos copiados (dependencias incluidas): tokens/tokens.css, core/base.css, core/canvas.js, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/particle-text/particle-text.js, components/particle-text/particle-text.css.
Uso
Marcado de referencia: parte de él y personalízalo con atributos, data-* y variables CSS:
<div style="display:grid;gap:.5rem;width:100%;justify-items:center">
<mv-particle-text id="mv-particle-text-demo" colors="var(--mv-accent), oklch(0.72 0.14 225), oklch(0.75 0.16 345)">Hello</mv-particle-text>
<div style="display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center">
<button class="mv-button" data-size="sm" data-variant="outline" data-word="Hello">Hello</button>
<button class="mv-button" data-size="sm" data-variant="outline" data-word="Marvelous">Marvelous</button>
<button class="mv-button" data-size="sm" data-variant="outline" data-word="Thanks!">Thanks!</button>
<button class="mv-button" data-size="sm" data-variant="ghost" id="mv-particle-text-demo-burst">Burst</button>
</div>
<p style="margin:.25rem 0 0;font-size:.8rem;color:var(--mv-fg-subtle)">Hover the letters to scatter them, click to make them explode.</p>
<mv-particle-text text="2026" style="font-size:3.5rem;max-width:320px;margin-top:.5rem" radius="50"></mv-particle-text>
</div>
<script type="module">
const pt = document.getElementById("mv-particle-text-demo");
for (const b of document.querySelectorAll("[data-word]")) b.addEventListener("click", () => { pt.text = b.dataset.word; });
document.getElementById("mv-particle-text-demo-burst").addEventListener("click", () => pt.burst());
</script>API
Attributes
| Name | Tipo | Default | Description |
|---|---|---|---|
text | string | Text (otherwise the element content). Changing it triggers a morph. | |
colors | list of CSS colors | var(--mv-particle-text-color) | One color, or several for a left-to-right gradient laid over the text; particles take the color of where they are (tokens accepted, they follow the theme). |
trigger | view | hover | load | manual | view | When the particles assemble (manual: call assemble()). |
gap | number | auto (2-8) | Sampling step in px (smaller = more particles, capped at 7,000; auto keeps the count under the cap). |
size | number | gap × 0.86 | Particle side length (px). |
radius | number | 90 | Cursor influence radius (px). |
strength | number | 1 | Repulsion strength. |
Methods
| Name | Description |
|---|---|
assemble() | Assembles the particles into text. |
burst(x?, y?) | Explodes the particles from a point (local coordinates, center by default). |
Events
| Name | Description |
|---|---|
mv-settle | All particles are back in place (the loop stops). |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-particle-text-color | var(--mv-fg) | Default color. |
Accessibility
The text stays available as visually hidden text for screen readers; the canvas is aria-hidden. Font family, weight and size come from the element's CSS (the text shrinks if it overflows). Reduced motion: text is assembled immediately, with no repulsion or explosion. Forced colors: particles use the system text color. The loop pauses off-screen and stops when idle.