ClickSpark

A burst of sparks where you click, drawn as streaks that shorten as they slow.

click the sheet

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

count 11

3 to 40, good: 8 to 16

Streaks in one burst. An odd number is better than an even one: an even fan has a streak opposite every other streak, which the eye reads as a cross.

bursts 4

1 to 10

How many bursts can be in the air at once. The newest win, so clicking faster than this does not cost more, it just drops the oldest burst early. Raising it raises the element count by the same factor.

colour #c44400

css colour

The spark. One colour, not a gradient and not a palette: a palette of sparks is confetti. If it has to work on both grounds, pick something that is neither nearly white nor nearly black.

speed 1.15

0.1 to 5

How fast a spark leaves, as a share of the shorter side of the element per second. Relative rather than in pixels, so the same burst looks right on a small button and on a full-page panel.

drag 0.22

0.02 to 2 s, good: 0.12 to 0.4

Seconds for a spark to lose most of its speed to the air. Short, and it is what makes the burst read as thrown rather than as expanding: the sparks go a long way in the first fifth of a second and then barely move.

gravity 0.55

0 to 5

How far the burst droops, as a share of the shorter side per second. At 0 the burst is perfectly symmetrical, which reads as a snowflake. It should be small enough that nobody would name it as falling.

life 0.62

0.1 to 3 s, good: 0.4 to 0.9

Seconds a spark lasts. This is feedback for a click, so it has to be over before the next thing happens: much past a second it stops being an acknowledgement and starts being an animation somebody has to wait out.

streak 0.055

0 to 0.3 s

How long a streak is, given as the seconds of travel it represents, so it is literally a shutter speed. At 0 the sparks are dots and the effect is confetti; long, and they are comet trails.

thickness 2

0.5 to 8 px

Thickness of a streak, in pixels rather than relative, because a hairline is a hairline at any size and a thick spark at small sizes is a blob.

scatter 0.45

0 to 1

How uneven the burst is. At 0 it is a perfect star, evenly spaced and all one length, which no two things striking each other have ever produced.

seed 7

0 to 9999

Seed for the scatter. Every burst already differs from the last, because the burst's own number goes into the hash; this moves the whole series, so two of these on one page are not twins.

What it needs

Category
Pointer, an effect
Dependencies
None at all
Browser
No WebGL
Frame budget
~0.5 ms · 0 context
Pinned to
v0.13.0
  • Each spark is drawn as a streak whose length is its current speed, which is what a short exposure of something hot and moving looks like. The streaks shorten on their own as the sparks slow, with nothing extra to animate, and it is the single difference between this and a particle demo
  • The sparks slow down. A spark meets air, so the distance is the integral of a decaying speed rather than speed times time. Linear motion outwards is the giveaway of every version of this: the burst expands like a diagram of an explosion instead of like one
  • A little gravity, so the burst is not symmetrical. Not enough to read as falling, just enough that it is not a snowflake
  • A fixed pool of elements, built once and reused. Bursts create and destroy nothing: a click takes the oldest slot, so forty clicks in a row cost exactly what four do. That matters because clicking it repeatedly is the first thing anybody does
  • The element keeps its own content. The streaks go in a layer over the top with pointer-events none, and the press is listened for on the element itself, so a button inside stays clickable and the feedback belongs to the thing that was pressed
  • Scripted presses and real ones are the same kind of event and go in the same list. The scripted ones are rebuilt from the options each frame rather than remembered, which is what keeps a scripted take pure in t: seeking backwards un-fires them
  • destroy() removes the layer and the listener and puts the element's position back
  • count times bursts elements, written every frame while anything is in the air and left alone when nothing is. At the defaults that is 44 elements, each one a composited transform and an opacity
  • No canvas, no WebGL context and no allocation during a burst. The arithmetic is two exponentials per spark