Skip to content
WANCRAFT

E.142Backgrounds & Effects

Particle Text

Type sampled into a swarm of particles that spring home, scatter from the pointer and re-form.

NewReactCanvasTailwindadvanced

Wancraft

Stir · click to scatter

Overview

Particle Text renders your text once to an offscreen canvas — in the container's own font, at the weight you choose, sized to fit — and samples its pixels on a grid. Every opaque sample becomes the home of a particle. Particles assemble from a scatter on first paint, spring home on fixed 60Hz steps, are pushed aside by the pointer (or a finger while it is down) and drift back; a click or tap blasts a hole that slowly heals. Colour modes include theme ink, the accent, an accent-to-secondary gradient, and a velocity mode where resting ink heats toward the accent as particles move. Changing the text, weight or density re-forms the existing particles rather than restarting. The text is exposed exactly once as screen-reader text, the canvas is aria-hidden, and reduced motion draws static particles with no pointer response.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/particle-text.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/particle-text.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/particle-text.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { ParticleText } from "@/components/ui/particle-text";

export function ParticleTextExample() {
  return (
    <div className="relative h-80 w-full overflow-hidden rounded-xl">
      <ParticleText />
    </div>
  );
}

03Props

PropTypeDefaultDescription
textstring"Wancraft"Text to draw. Exposed once to assistive tech; one line, fitted to the container.
as"h1" | "h2" | "h3" | "p" | "span""p"Element used for the screen-reader copy of the text.
fontWeightnumber700Font weight, 100–900. The font family is inherited from the container.
particleSizenumber2Particle diameter in px (round from 2px, square below).
densitynumber0.6Sampling density 0.2–1 (about 7.7px to 2.5px between particles); capped at 7,000 particles.
colorMode"velocity" | "ink" | "accent" | "gradient""velocity"Ink that heats toward the accent with speed, theme ink, the accent, or an accent → secondary gradient.
radiusnumber100Pointer repel radius in px; clicks scatter within 2.2× this.
accentstring"#FF7448"Accent colour (any CSS colour).
secondarystring"#B6F3D1"Second colour of the gradient mode (any CSS colour).
...propsHTMLAttributes<HTMLDivElement>—Forwarded to the root, which is absolute inset-0 — place it inside a positioned parent.

04Features

  • 01Text sampled from an offscreen canvas in the container's font; size fitted to width and height
  • 02Damped spring per particle on fixed 60Hz steps; the loop sleeps once everything has settled
  • 03Pointer repel with a smooth falloff, click/tap scatter, touch follows the finger while it is down
  • 04Velocity colour mode buckets particles by speed, so stirred text glows in the accent
  • 05Prop changes re-form the existing swarm instead of restarting; re-samples when web fonts finish loading
  • 06DPR-aware canvas (capped at 2), ResizeObserver, pauses offscreen and in hidden tabs, theme-aware ink
motion · springmotion · continuousinput · pointerinput · clickinput · viewport

05Accessibility

  • The text is rendered once as visually hidden text (configurable element, e.g. an h1) so screen readers read it exactly once.
  • The canvas is aria-hidden and ignores pointer events.
  • prefers-reduced-motion draws static particles at their homes, with no assembly, pointer response or scatter.

06Limitations

  • Single line only; long strings shrink to fit the width.