Skip to content
Founding Lifetime: every Pro skillfirst 100 members · $169 onceUpgrade
Lookbk
Sign In
Effect guide

Particle effect for a website: how it works, with code

Thousands of small dots that swarm, settle into a word or a picture, and scatter when the pointer passes. How a particle animation works, a canvas starter that builds text out of particles, and the skills that build a finished particle hero.

Free skills to start. Pro is $79 a year for every skill, or $9.99 a month for 10. See pricing

What is a particle effect?

A particle effect draws something out of many small, simple pieces, each moving on its own. Smoke, sparks, snow, dust and fireworks are the classic ones in games and film. On websites the favorite is a swarm of dots that settles into a shape, such as a word, a logo or a face, and breaks apart when you reach for it.

It works because the eye reads the shape from the crowd while every dot keeps moving a little, so the picture is there and not there at once. That suits AI, data, science and creative brands, launch pages and portfolios. The catch is that thousands of moving dots can bury a headline or drain a phone, so the craft is in restraint.

How the effect works

Each particle is a few numbers: a position, a velocity and, for a shape, a home, the point it belongs to. To find the homes, draw the word or image on a hidden canvas, read its pixels with getImageData and keep one point for every filled cell of a grid. Every frame, add the forces to the velocity, add the velocity to the position, and draw.

Most particle animations come down to three forces. A spring pulls each particle toward its home, so the shape forms and forms again. A push away from the pointer, strongest close to it, makes the shape react. Friction takes a little speed away every frame, so particles settle instead of wobbling forever. Change the balance and the same code gives you a jelly, a swarm or a sandstorm.

  1. 01

    Sample the shape

    Draw the text or image off screen and keep one point every few pixels where it is opaque. The grid spacing sets how many particles there are.

  2. 02

    Spring them home

    Each frame, add a small fraction of the distance to home to the velocity. A small fraction gives a slow, loose assembly; a large one snaps into place.

  3. 03

    Push from the pointer

    Within a radius of the pointer, push particles straight away from it, harder the closer they are.

  4. 04

    Damp, then draw

    Multiply the velocity by about 0.85 to 0.95 every frame, then draw each particle as a small square or dot. Squares are cheaper to draw than circles.

HTML

A canvas particle effect in plain JavaScript

Draws a word off screen, turns every filled cell of a 6 px grid into a particle, flies them in to assemble it, and scatters them away from the pointer before springs pull them home. Change TEXT, GAP and REACH for another word, density or reach. Reduced motion gets the assembled word.

<canvas id="dots" style="position:fixed;inset:0;width:100%;height:100%;background:#071014"></canvas>
<script>
const TEXT = 'Particles' // the word the particles build
const GAP = 6, REACH = 90 // CSS px between particles, pointer radius
const canvas = document.getElementById('dots')
const g = canvas.getContext('2d')
const still = matchMedia('(prefers-reduced-motion: reduce)').matches
let w, h, dpr, parts = []
const pointer = { x: -1e4, y: -1e4 }

function build() {
  dpr = Math.min(devicePixelRatio, 2)
  w = canvas.width = innerWidth * dpr
  h = canvas.height = innerHeight * dpr
  // 1. draw the word off screen and read its pixels
  const off = document.createElement('canvas'), o = off.getContext('2d')
  off.width = w; off.height = h
  o.font = '800 ' + Math.min(w / (TEXT.length * 0.62), h * 0.4) + 'px system-ui, sans-serif'
  o.textAlign = 'center'; o.textBaseline = 'middle'
  o.fillText(TEXT, w / 2, h / 2)
  const px = o.getImageData(0, 0, w, h).data, step = Math.round(GAP * dpr)
  // 2. one particle per filled grid cell, starting scattered
  parts = []
  for (let y = 0; y < h; y += step)
    for (let x = 0; x < w; x += step)
      if (px[(y * w + x) * 4 + 3] > 128) parts.push({
        hx: x, hy: y, // home
        x: still ? x : Math.random() * w, y: still ? y : Math.random() * h,
        vx: 0, vy: 0, hue: 160 + (x / w) * 60,
      })
}
build(); addEventListener('resize', () => { build(); if (still) frame() })

const aim = (e) => { pointer.x = e.clientX * dpr; pointer.y = e.clientY * dpr }
const away = () => { pointer.x = pointer.y = -1e4 }
addEventListener('pointermove', aim); addEventListener('pointerdown', aim)
addEventListener('pointercancel', away) // a finger that starts scrolling
addEventListener('pointerup', (e) => { if (e.pointerType !== 'mouse') away() })
document.addEventListener('pointerout', (e) => { if (!e.relatedTarget) away() })

let last = performance.now()
function frame(now = last) {
  const dt = Math.min(0.033, Math.max(0, now - last) / 1000) * 60; last = now // 1 = one 60 Hz frame
  g.fillStyle = still ? '#071014' : 'rgba(7,16,20,0.3)' // a faint trail behind moving particles
  g.fillRect(0, 0, w, h)
  const r = REACH * dpr, size = Math.max(1, GAP * dpr * 0.45)
  for (const p of parts) {
    if (!still) {
      // 3. a spring pulls each particle home...
      p.vx += (p.hx - p.x) * 0.012 * dt
      p.vy += (p.hy - p.y) * 0.012 * dt
      // 4. ...and the pointer pushes it away
      const dx = p.x - pointer.x, dy = p.y - pointer.y, d2 = dx * dx + dy * dy
      if (d2 < r * r && d2 > 0.01) {
        const d = Math.sqrt(d2), push = (1 - d / r) * 2.4 * dt
        p.vx += (dx / d) * push; p.vy += (dy / d) * push
      }
      p.vx *= Math.pow(0.88, dt); p.vy *= Math.pow(0.88, dt) // friction
      p.x += p.vx * dt; p.y += p.vy * dt
    }
    const speed = Math.min(1, Math.hypot(p.vx, p.vy) / 8)
    g.fillStyle = 'hsl(' + (p.hue - speed * 120) + ',90%,' + (60 + speed * 25) + '%)'
    g.fillRect(p.x - size / 2, p.y - size / 2, size, size)
  }
  if (!still) requestAnimationFrame(frame)
}
frame()
</script>

A starting point written for this page, free to use in your own projects. The skills below build the finished version with checks, fallbacks and a recorded video.

What to get right on a real page

  1. 01

    Count your particles

    A few thousand squares on a 2D canvas run smoothly; tens of thousands need WebGL points, which is what three.js particle heroes use. Cap the device pixel ratio at 2 and use a coarser grid on phones.

  2. 02

    Keep the headline as real text

    A word made of particles can’t be read by screen readers or search engines, and it blurs while it moves. Put the real headline in HTML and let the particles echo it or sit beside it.

  3. 03

    Don’t trap touch

    On phones a drag scrolls the page. React to taps, or let the effect run on its own; never block scrolling to follow a finger.

  4. 04

    Pause out of view

    Stop the animation loop when the hero scrolls off screen, with an IntersectionObserver, and start it again when it comes back.

  5. 05

    Hold a still frame for reduced motion

    Respect prefers-reduced-motion: show one finished frame instead of the loop. A visitor who turned motion off still gets the look.

Skills that build a particle effect

Finished particle heroes built on three.js with hand-written shaders, in your colors, fonts, logo and words, checked at four widths, with a 1080p video for launch posts. One builds your own photo or logo out of dots; the other grows a structure from them.

  1. Particle Portrait Hero: an example of what it makes
    web
    Particle Portrait HeroClaude CodeCodexCursor+3 more agents

    Motion Heroes · Pro

    Particle Portrait Hero

    One HTML page + embed · MP4 + poster

    Your own photo or logo turned into thousands of dots in 3D, each set forward or back by the brightness under it, so the picture has relief. The dots fly in and assemble; then, as the visitor scrolls, the hero pins and the picture turns to show its depth, peels away into a slow orbit of dots and comes back together, with the pointer sending ripples through it. The dots take a two-color duotone or the picture’s own colors.

    Worth knowing: The relief is an illusion taken from brightness, not a 3D scan, and a cut-out or a picture on a transparent background works best.

    Needs: Node.js 18+, Chrome for the checks and recording, ffmpeg for the video, and your photo or logo (SVG, PNG, JPEG or WebP; a cut-out or transparent background works best)

    See what Particle Portrait Hero makes
  2. Particle Tree Hero: an example of what it makes
    web
    Particle Tree HeroClaude CodeCodexCursor+3 more agents

    Motion Heroes · Pro

    Particle Tree Hero

    Animated WebGL hero · page + embed + 1080p video

    A glowing tree with roots, or a neuron with dendrites and an axon, grows out of the dark from thousands of soft particles over hairline branches. Once it has grown, light pulses run along its branches and flash where they arrive, buds twinkle, the wind moves the crown and motes drift past, while a small readout counts nodes, growth and signals. It is seeded, so the same settings always grow the same shape.

    Worth knowing: It needs a near-black background. The branches come from a seed and the readout follows the animation, not your real data.

    Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video

    See what Particle Tree Hero makes

Install

Build a particle effect with your agent

Each skill is a SKILL.md folder, so it installs the same way in Claude Code, Codex, Cursor and other agents. The example below uses Particle Portrait Hero; each skill page has its own prompt.

1. Paste the install prompt

Your agent runs the installer. The first time, it shows a sign-in link so you can approve it in the browser.

Install the "Particle Portrait Hero" skill from Lookbk (https://lookbk.dev/skills/particle-portrait-hero).
1. Run: curl -fsSL https://lookbk.dev/cli.js | node - add particle-portrait-hero
2. If it prints a sign-in link, show it to me. When I say I approved it, run the same command again.
3. When the install finishes, read the SKILL.md it installed and tell me what you need from me to make the first result.

Or run it in a terminal

curl -fsSL https://lookbk.dev/cli.js | node - add particle-portrait-hero

2. Start a new session

Agents load skills when a session starts. The installer writes the folder where your agent looks:

Claude Code
~/.claude/skills/particle-portrait-hero
Codex
~/.agents/skills/particle-portrait-hero
Cursor
~/.agents/skills/particle-portrait-hero

3. Ask for the result

Describe it in plain words, for example:

Make a Particle Portrait hero for Signal Hours, my weekly interview show: use my cut-out portrait, navy background with blue shadows and warm amber lights, the headline 'Long talks, slowly made.' and a 'Play episode 112' button, with three story labels in the corner. Record a video for the launch post.

Another agent? Install a skill in any agent

FAQ

Questions

Still stuck? The guides cover installing, agents and licensing in more detail.

Read the guides
How do I make a particle effect in JavaScript?

Keep an array of particles, each with a position and a velocity, update them on every requestAnimationFrame and draw them on a canvas. For particles that form text or a logo, sample the shape’s pixels from a hidden canvas to give each particle a home, as the starter does.

Can I make a particle animation with CSS only?

For a few dozen particles, yes: absolutely positioned dots, each with its own keyframes and delay. CSS can’t sample a shape or move each particle away from the pointer, so text, pictures and swarms of thousands need canvas or WebGL.

Should I use canvas or WebGL for particles?

Canvas 2D is simpler and handles a few thousand particles. WebGL, often through three.js, draws tens of thousands as points on the GPU and adds depth and glow. Particle Portrait Hero draws its picture as a three.js point cloud of about 15,000 to 25,000 dots at its default grid.

Can I use a library like tsParticles instead?

Yes. Libraries such as tsParticles give you configurable presets, such as linked dots, snow and confetti. For particles that build your own word, photo or logo, the sampling in the starter is short enough to write yourself.

Can I turn my own photo into particles?

Yes. Sample the photo instead of text and color each particle from the pixel under it. A cut-out on a transparent background gives the cleanest edge. Particle Portrait Hero does this with your photo or logo and sets each dot’s depth from its brightness.

Can I get the particle hero as a video?

Yes. Both skills record a frame-perfect 1080p MP4 and a poster, with portrait sizes too. Particle Portrait Hero’s video replays a scripted scroll through its story; Particle Tree Hero’s shows the structure growing, then the pulses.