Cursor trail effect for a website
A line, a run of dots or a stack of photos that follows the pointer and fades behind it. The kinds of cursor trail, how to keep one smooth, a canvas starter you can paste and run, and the skills that build a finished hero around it.
Free skills to start. Pro is $79 a year for every skill, or $9.99 a month for 10. See pricing
What is a cursor trail?
A cursor trail is whatever a web page leaves behind the pointer as it moves: a glowing ink line that thins and fades, a string of dots or sparks, or an image trail that drops photos along the path. It is drawn by the page for every visitor, which makes it a different thing from the pointer trails setting in Windows or a browser extension that changes your own cursor.
Three kinds cover most of what you see. An ink or particle line draws a stroke through the last few pointer positions and fades it by age. Fading dots stamp a shape every few pixels of travel. An image trail deals pictures along the path and retires the oldest, which suits photographers, galleries and studios, because the trail is the portfolio. A quieter cousin is a light or a field that follows the pointer and leaves a short wake, like a spotlight over type or dots that part and ripple.
It works best in one section, usually the hero, where moving the mouse is part of the first impression. Spread across a whole site, it gets in the way of reading and clicking.
How the effect works
Listen to pointermove and remember the latest position, but do the drawing once per animation frame. A mouse can fire hundreds of events a second; drawing on each one wastes work and makes the trail uneven.
For a smooth line, let a head point chase the pointer instead of jumping to it: each frame it covers a share of the remaining distance (a lerp), or moves on a spring if you want a little overshoot. Add a trail point whenever the head has traveled a few pixels, draw from the oldest point to the newest with width and opacity tied to each point’s age, and drop points older than the trail’s life.
One canvas over the page handles hundreds of points cheaply. DOM elements, a div per dot or an img per photo moved with transform, are fine for a dozen items and are easier to style, but changing top and left or reading layout on every move makes the page stutter.
01
Sample by distance, not by event
Add a point when the pointer has moved a few pixels. A slow drag and a fast flick then give the same density, and an image trail drops a photo every 80–150 px instead of on every event.
02
Ease the head
head += (pointer − head) × (1 − e^(−rate × seconds)). The trail lags a touch and smooths jittery input at any frame rate.
03
Fade by age
Store the time with each point. Opacity and width fall from full to zero over the trail’s life, so the tail tapers on its own.
04
Stop when idle
When the pointer rests and the last point has faded, stop requesting frames. An idle trail should cost nothing.
HTML
A canvas cursor trail in plain JavaScript
An ink line that eases after the pointer and fades over 0.6 seconds, on a canvas that lets clicks through, so the real cursor stays. Touch screens get a ring per tap, reduced motion gets no trail, and it stops drawing when idle.
<style>body { margin: 0; min-height: 100vh; background: #0e0f14 }</style>
<canvas id="trail" aria-hidden="true" style="position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:10"></canvas>
<script>
const canvas = document.getElementById('trail')
const g = canvas.getContext('2d')
const LIFE = 0.6, STEP = 6, FOLLOW = 18 // seconds a point lives, px between points, spring rate
const still = matchMedia('(prefers-reduced-motion: reduce)').matches
const touch = matchMedia('(pointer: coarse)').matches
let w, h, dpr
function size() {
dpr = Math.min(devicePixelRatio, 2)
w = canvas.width = innerWidth * dpr
h = canvas.height = innerHeight * dpr
}
size(); addEventListener('resize', size)
const pts = [] // { x, y, t, cut }: cut starts a new stroke
const target = { x: 0, y: 0 }, head = { x: 0, y: 0 }
let running = false, seen = false, last = 0
function wake() {
if (running) return
running = true; last = performance.now(); requestAnimationFrame(frame)
}
if (!still && !touch) addEventListener('pointermove', (e) => {
target.x = e.clientX * dpr; target.y = e.clientY * dpr
if (!seen) { head.x = target.x; head.y = target.y; seen = true }
wake()
})
// Touch has no hover: a tap draws one small ring that fades instead.
if (!still && touch) addEventListener('pointerdown', (e) => {
const now = performance.now()
for (let i = 0; i <= 24; i++) {
const a = (i / 24) * Math.PI * 2
pts.push({ x: (e.clientX + Math.cos(a) * 18) * dpr,
y: (e.clientY + Math.sin(a) * 18) * dpr, t: now, cut: i === 0 })
}
wake()
})
function frame(now) {
const dt = Math.min(0.05, (now - last) / 1000); last = now
if (seen) {
const k = 1 - Math.exp(-FOLLOW * dt) // the head eases after the pointer
head.x += (target.x - head.x) * k; head.y += (target.y - head.y) * k
const p = pts[pts.length - 1]
if (!p || Math.hypot(head.x - p.x, head.y - p.y) > STEP * dpr)
pts.push({ x: head.x, y: head.y, t: now, cut: !p })
}
while (pts.length && now - pts[0].t > LIFE * 1000) pts.shift()
g.clearRect(0, 0, w, h)
g.lineCap = 'butt'; g.lineJoin = 'round'
for (let i = 1; i < pts.length; i++) {
const a = pts[i - 1], b = pts[i]
if (b.cut) continue
const age = 1 - (now - b.t) / (LIFE * 1000) // 1 new, 0 gone
g.strokeStyle = 'hsla(' + (190 + 130 * (1 - age)) + ',90%,62%,' + age + ')'
g.lineWidth = (1 + 9 * age) * dpr
g.beginPath(); g.moveTo(a.x, a.y); g.lineTo(b.x, b.y); g.stroke()
}
const moving = Math.hypot(target.x - head.x, target.y - head.y) > 0.5
if (pts.length || (seen && moving)) requestAnimationFrame(frame)
else running = false // idle: no frames at all
}
</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
01
Keep the real cursor
Draw the trail behind the pointer, never instead of it. Hiding the cursor with cursor: none breaks text selection and link hover and loses the visitor’s sense of where they are. Set pointer-events: none on the trail layer so every click goes through.
02
Plan for touch
Phones and tablets have no hover, so there is nothing to follow until a finger is down, and a drag scrolls the page. Show the hero without the trail, react to taps, or play a short scripted path; never block scrolling to capture a finger.
03
Keep it off the copy
A trail crossing the headline pulls the eye away from the words. Fade it under text, or keep it to the bands above and below the headline.
04
Watch the cost
Cap the device pixel ratio at 2, keep a few hundred points at most, never read layout inside the move handler, and stop the loop when the pointer is still.
05
Turn it off for reduced motion
When prefers-reduced-motion is set, skip the trail; the page must work the same without it. Mark the trail layer aria-hidden, since it carries no content.
Skills that build a cursor trail
Finished heroes where the pointer leaves something behind, with your colors, fonts, logo and words, and a 1080p video for launch posts.
- Image TrailClaude CodeCodexCursor+3 more agents
Motion Heroes · Pro
Image Trail
Image trail hero · page + embed · 1080p loop
An image trail: moving the pointer deals prints onto a table. Each print falls, slides on in the direction of travel and settles at its own angle with a two-layer shadow, dries, fades the way photographs fade and is picked up, so the trail reads as a gradient of time. It deals by distance, so a slow drag lays an overlapping fan and a fast sweep spreads the prints out; a tap deals one, and on phones the hand runs a path that never rests a print on the headline.
Worth knowing: The pictures are drawn in code (photographic prints, paint cards, fabric and plaster chips), not your own photos.
Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video
See what Image Trail makes - Dot Field HeroClaude CodeCodexCursor+3 more agents
Motion Heroes · Pro
Dot Field Hero
Canvas 2D dot field · page + embed · 1080p loop
A field of thousands of dots that act like iron filings near a magnet. Dots near the cursor are pushed aside, grow and light up in the accent color, then spring back past home and settle, and rings spread from the cursor’s trail and fade. With no pointer, on phones and in the video, a virtual cursor glides on a closed path.
Worth knowing: The trail is ripples in a fixed grid of dots inside the hero, not a line or images.
Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video
See what Dot Field Hero makes - Blueprint Flashlight HeroClaude CodeCodexCursor+3 more agents
Motion Heroes · Pro
Blueprint Flashlight Hero
Canvas 2D blueprint reveal · page + embed · 1080p loop
A warm lamp follows the pointer on a spring over a technical drawing and leaves a short fading trail. Inside the light a product appears in fine lines with dimensions and numbered callouts, and each callout types in while the light rests on it. Without a pointer it tours the sheet on a closed path.
Worth knowing: The five product drawings are generic and made in code, not your own product’s design.
Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video
See what Blueprint Flashlight Hero makes - Spotlight Type HeroClaude CodeCodexCursor+3 more agents
Motion Heroes · Pro
Spotlight Type Hero
Canvas 2D spotlight on a type wall · page + embed · 1080p loop
A dark wall of giant type where a soft spotlight follows the pointer and shows the words underneath in bright gradient fill, with a smaller second light trailing behind it. One row hides a line, such as a date, an offer or a launch, that appears only under the light. On touch screens the light follows a finger while it drags.
Worth knowing: The hidden line holds 24 characters, and the dark wall feels heavy on bright, airy pages.
Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video
See what Spotlight Type Hero makes
Install
Build a cursor trail 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 Image Trail; 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 "Image Trail" skill from Lookbk (https://lookbk.dev/skills/image-trail-hero). 1. Run: curl -fsSL https://lookbk.dev/cli.js | node - add image-trail-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 image-trail-hero2. Start a new session
Agents load skills when a session starts. The installer writes the folder where your agent looks:
- Claude Code
- ~/.claude/skills/image-trail-hero
- Codex
- ~/.agents/skills/image-trail-hero
- Cursor
- ~/.agents/skills/image-trail-hero
3. Ask for the result
Describe it in plain words, for example:
Build a website hero where moving the pointer deals a trail of code-drawn prints onto a linen table: each lands at a slight angle with a real shadow, dries, fades like an old photograph and is picked up, while the headline stays readable on the table.
Another agent? Install a skill in any agent
FAQ
Questions
Still stuck? The guides cover installing, agents and licensing in more detail.
Read the guidesHow do I make a cursor trail in CSS?
CSS cannot read the pointer position, so you need a few lines of JavaScript. A light version is a handful of absolutely positioned dots: on pointermove, set every dot’s transform to the pointer position and give each a slightly longer transition, so they arrive one after another. For more than a dozen dots, or a fading line, use a canvas.
How do I make an image trail that follows the cursor?
Keep a pool of images and count the distance the pointer travels. Each time it passes a threshold, around 100 px, place the next image at the pointer with a small random turn, animate it in, fade it out after a second or two and reuse it. Image Trail does this with prints drawn in code, dealt by distance, each fading before it is picked up.
Does a cursor trail work on phones?
Not as a trail. Touch screens have no hover, so there is no pointer to follow until a finger is down, and a drag scrolls the page. Show the hero without the trail, react to taps, or play a short scripted path. The starter draws a ring on each tap.
Is this the same as Windows pointer trails or a cursor extension?
No. Windows pointer trails and browser extensions change your own cursor on your own computer. A website cursor trail is drawn by the page, for every visitor, and only on that page.
Can I get the trail as a video?
Yes. Image Trail records a frame-exact looping 1080p MP4 in which the hand follows its scripted path, so the trail plays in posts where nobody moves a mouse.



