Every effect in this batch is drawn by hand-rolled math against the Canvas 2D API — no WebGL, no physics engine, no noise library. A fractal tree is one recursive function calling itself twice. A rope is Verlet integration with an iterative constraint solver. A lightning bolt is the same midpoint-displacement algorithm used to generate fractal coastlines, aimed at a click point instead of a landscape. None of it is faked with a canned particle sprite or a CSS animation standing in for the real computation — the algorithm is genuinely running, which is exactly what makes each one worth reading the source of, not just dropping in.
Below are ten free, self-contained snippets spanning recursive drawing, from-scratch Perlin noise, N-body gravity, and a few honest tricks — a CSS blur doing the work a shader normally would, a nearest-neighbor upscale turning a blur into a crisp pixelated look instead. Every one is a live, interactive preview you can try right here in the article, and each exports to React, Vue, Angular or Tailwind in one click from its snippet page.
What these ten get right
- Recursion can be the entire data structure. The fractal tree's
branch()function draws one segment and calls itself twice — there's no tree object built in memory anywhere; the call stack is the tree, and color, width, and wind sensitivity all fall out of the samedepthvalue already being tracked for recursion. - The same fractal technique generates both terrain and lightning. Recursive midpoint displacement — nudge a segment's midpoint perpendicular to itself, then recurse on both halves with a shrinking displacement budget — is what the noise terrain uses for coastlines and what the lightning bolt uses for its jagged path. Same math, different target.
- Position-based physics sidesteps an entire class of instability. The rope stores current and previous position instead of velocity, deriving motion implicitly as
(current - previous)— that's Verlet integration, and it's what makes an iterative distance-constraint solver trivial instead of fighting a spring-force model. - A real physics formula still needs a stability patch. The gravity simulation computes actual inverse-square attraction, but a raw
1/distance²blows up to infinity as a particle passes close to a well — adding a small constant to the squared distance before dividing (force softening) caps it without a special-case collision check. - Sometimes the honest move is to let CSS do the hard part. The mesh gradient background draws sharp, cheap circles at reduced resolution and lets a single
filter: blur(60px)do all the softening on the compositor — no manual convolution, and the JavaScript never has to know blurring is happening at all.
1. Canvas Fractal Tree Generator
A recursive tree that sways toward the cursor like wind, where the entire branching structure is one function calling itself twice — no tree data structure exists anywhere in memory.
How it works: every call to branch() draws one line segment from a start point at a given angle and length, then recurses exactly twice — once angled left by the spread, once right — each with a shrunken length and one less depth remaining. The recursive call stack is the tree; nothing else stores its structure. Line width, color, and leaf dots are all derived from the current depth relative to maxDepth inside the same recursive call, and cursor position sets a targetSway value eased into every branch's angle, scaled by a windFactor that grows the further a branch sits from the trunk — so outer twigs visibly sway more, reusing the same depth value already tracked for recursion.
Best for: recursion teaching demos and nature/eco brand landing pages that want an organic, growing visual metaphor. Tip: drive an incrementing depth variable over time instead of a fixed slider value to turn this into an animated growth sequence with zero other code changes.
Grab the code: Canvas Fractal Tree Generator
2. Canvas Procedural Lightning
Click anywhere and a jagged, branching bolt strikes from the top of the sky — generated with recursive midpoint displacement, the same fractal technique used to generate terrain heightmaps and coastlines.
How it works: displace() takes a straight segment, finds its exact midpoint, nudges it perpendicular to the segment by a random amount, then recurses on both resulting sub-segments with a smaller displacement budget (maxOffset * 0.55). Because each recursion level operates on a shorter segment with a proportionally smaller budget, the result has large kinks at the coarse level and progressively finer kinks nested inside them — genuine self-similar roughness, not a scribble of random points. Displacement is constrained to strictly perpendicular, which is what keeps the bolt progressing toward its target instead of doubling back on itself; branches reuse the identical displace() function at a smaller depth, which is why they read as belonging to the same bolt rather than a separately-drawn effect.
Best for: weather/storm-themed landing pages and high-energy gaming or event hero backgrounds that want a real click-triggered attention effect. Tip: the whole-canvas white flash on each strike is just a flash value spiking to 1 and decaying exponentially, swapped in for the normal translucent fade fill while it's above a threshold.
Grab the code: Canvas Procedural Lightning
3. Canvas Rope Physics
A draggable rope pinned at both ends that sags, swings, and holds its length under an adjustable stiffness — simulated with Verlet integration and iterative constraint solving, the same class of technique behind game rope and cloth.
How it works: each rope point stores its current and previous position, never an explicit velocity — every frame, velocity is derived implicitly as (x - px), damped by friction, and projected forward plus gravity. That's Verlet integration, and it's numerically stable in a way that makes distance constraints trivial to enforce directly on position. Every stick between adjacent points is a rigid-distance constraint that satisfyConstraints() corrects by nudging both points toward the right separation; running that pass multiple times per frame — the Stiffness slider maps straight to iteration count — is what makes the rope feel taut instead of stretchy elastic. While dragging a point, both its current and previous position are set to the pointer position every move event, which zeroes its implicit velocity so it doesn't fling on release.
Best for: physics/game-dev teaching demos and playful draggable elements in an interactive hero section. Tip: extend the same points-and-sticks topology into a 2D grid with diagonal constraints for cloth — the integration and constraint-solving code needs no changes, only the topology does.
Grab the code: Canvas Rope Physics
4. Canvas Gravity Particle Orbits
Hundreds of particles orbit user-placed gravity wells under a real inverse-square attraction force, curving sharply on close passes without ever slingshotting to infinity.
How it works: every frame, each particle sums a force of (G * mass) / distance² from every active well, directed along the vector between them — literally Newton's law of gravitation, with G tuned for canvas scale rather than SI units. A raw inverse-square force approaches infinity as distance approaches zero, which would fling any particle straying too close out at simulation-breaking speed; adding a small constant to the squared distance before dividing (force softening, a standard N-body technique) caps the force at close range with no special-case collision check. Initial velocities use the real circular-orbit-speed formula sqrt(G * mass / distance) but randomized around it, which is what produces a genuine mix of ellipses, spirals, and slingshot escapes instead of one repetitive, mathematically perfect circle.
Best for: astronomy/physics teaching demos and space-themed landing pages that want an ambient background grounded in real orbital math. Tip: clicking to add a second well requires zero new code — the force-summing loop already iterates over every well for every particle, so existing orbits immediately reorganize around the combined field.
Grab the code: Canvas Gravity Particle Orbits
5. Canvas Fluid Cursor Trail
A soft, glowing trail of stretched blobs that follows the cursor — an honest, lightweight approximation of a fluid look, not a Navier-Stokes solver pretending to be one.
How it works: every pointer move computes a velocity vector against the last recorded position, and that single vector drives three things at once — the new blob's drift, its stretch factor (ctx.rotate plus ctx.scale elongate it along the direction of travel), and its hue, so a fast flick reads visually differently from a slow drag. Each blob draws with globalCompositeOperation = 'lighter', which adds color where blobs overlap instead of layering opaque shapes — that additive blowout near the cursor, combined with each blob's soft radial-gradient falloff, is most of what sells the glow. The trail fades not by tracking a history array but by painting a low-opacity dark rectangle over the whole canvas before every new frame, letting old blobs dim across several frames for free.
Best for: creative-agency hero backgrounds and music/event pages that want an energetic, motion-forward cursor accent. Tip: swap globalCompositeOperation to 'screen' or 'overlay' for a different blend character without touching any of the physics.
Grab the code: Canvas Fluid Cursor Trail
6. Canvas ASCII Art Converter
A generated scene rendered live as ASCII characters, sampling real pixel brightness cell by cell against a swappable character ramp — no image upload, no library.
How it works: since a self-contained snippet has nowhere reliable to host a photo, a procedural scene — gradient sky, radial-gradient sun, a sine-perturbed mountain silhouette, scattered stars — is painted onto an offscreen canvas purely to give the sampler real light-to-dark range to react to. getImageData returns a flat RGBA byte array, and the render loop walks the canvas in cell-sized steps, converting each sampled pixel to brightness with the standard luminance weighting r*0.299 + g*0.587 + b*0.114 — which accounts for the eye's higher sensitivity to green, so the result tracks perceived lightness rather than a flat channel average. That brightness indexes into a character ramp ordered from sparse to dense, and the chosen glyph draws directly with fillText at the cell's coordinates — the ASCII output lives entirely on the canvas, no overlaid <pre> block to keep in sync.
Best for: developer portfolio heroes and retro/hacker-themed pages, and as a teaching example for getImageData and pixel math. Tip: swap paintSourceImage() for ctx.drawImage(yourImg, 0, 0) once a same-origin image has loaded to convert real photos through the identical sampling pipeline.
Grab the code: Canvas ASCII Art Converter
7. Canvas Noise Terrain Generator
A topographic-style landscape generated from a from-scratch Perlin noise implementation, stacked into fractal Brownian motion and colored by elevation band.
How it works: a shuffled 256-entry permutation table assigns each integer lattice point a pseudo-random gradient direction, and noise2D() smoothly interpolates between the dot products of surrounding lattice gradients — classic gradient noise, which produces spatially coherent randomness instead of per-pixel static. A single octave alone produces smooth, blobby shapes with no fine texture, so fbm() sums several octaves at doubling frequency and halving amplitude: low-frequency octaves set the broad hills and valleys, high-frequency ones layer in coastline roughness on top — real fractal Brownian motion, the same technique actual terrain-generation systems use. Rather than a smooth color gradient, height maps through a fixed sequence of elevation-band thresholds (water, beach, grass, forest, rock, snow) with interpolation only within each band, which is what makes the field read as a legible map instead of an abstract color blend.
Best for: game-dev/worldbuilding reference and generative-art hero backgrounds that want a genuinely unique layout on every load. Tip: offset the noise coordinates by a slowly incrementing value inside a requestAnimationFrame loop instead of only regenerating on click, for a continuously scrolling terrain with no other logic changes.
Grab the code: Canvas Noise Terrain Generator
8. Canvas Kaleidoscope Drawing
A drawing pad where every stroke replays as rotated and mirrored copies around a shared center — true reflective symmetry, not just a rotated pinwheel repeat.
How it works: the core is a plain 2D rotation of a point around the canvas center, applied once per symmetry segment spaced evenly around a full circle. A purely rotated repeat produces a pinwheel, not a kaleidoscope — so for every rotated copy, a second copy negates the segment's y-offset from center before rotating, mirroring the stroke across the local axis first. Combining a mirrored copy with each rotated copy is specifically what produces true reflective symmetry, where each wedge is a mirror of its neighbor rather than an identical rotated repeat. Every mousemove event stamps just the newest line segment straight onto the canvas, rotated and mirrored, with no separate path array to manage — the canvas itself is the only state, exactly like an ordinary paint app.
Best for: meditation/wellness apps wanting a calming mandala-style focus activity, and kids/educational sites for an accessible symmetry-drawing exercise. Tip: the mirror axis is currently fixed to the horizontal, which can leave a faint seam — recompute the mirror axis per-wedge based on that wedge's own rotation angle for a fully seamless mandala.
Grab the code: Canvas Kaleidoscope Drawing
9. Canvas Pixelate Image Reveal
Cards that sharpen from a chunky mosaic to full detail on scroll-into-view or hover — the "developing photograph" effect, built from exactly one canvas property most people never touch.
How it works: the full-detail source is drawn once, at native resolution, onto its own untouched offscreen canvas — every reveal frame downsamples fresh from that same source, so quality never degrades across repeated hover cycles the way it would if the visible canvas were resized in place repeatedly. To render at a given "resolution," the source is first drawn down onto a tiny intermediate canvas only a handful of pixels wide, then that tiny canvas is drawn back onto the visible canvas at full size with imageSmoothingEnabled = false on the destination — that single boolean switches the browser's upscale from blurry bilinear interpolation to nearest-neighbor, which is the entire difference between "pixelated" and "blurry." Resolution eases toward its target by a fixed fraction of the remaining distance each frame rather than jumping straight there, and both hover and an IntersectionObserver scroll trigger call the identical reveal() function — no duplicated logic between the two trigger paths.
Best for: portfolio and gallery grids that want intrigue before a project thumbnail resolves, and photography portfolios wanting a deliberate "developing" moment. Tip: tie the target cell count to scroll progress within the viewport instead of a boolean trigger for a scrubbable, rather than one-shot, reveal.
Grab the code: Canvas Pixelate Image Reveal
10. Canvas Mesh Gradient Background
Soft, saturated color blobs orbiting slowly and blending into the animated mesh-gradient look every SaaS marketing page seems to have now — with the actual blur coming from one line of CSS, not the JavaScript.
How it works: every blob is a plain createRadialGradient circle drawn with hard mathematical precision — full color at center, fading to transparent at the edge. None of the softness is drawn; filter: blur(60px) saturate(1.3) on the canvas element in CSS is what turns those crisp circles into the smooth, melting fields the effect is known for, handled by the compositor at essentially no extra per-frame cost. Because a 60px blur erases fine detail regardless of source resolution, the canvas's actual backing store is deliberately sized to only 60% of the wrapper's dimensions — drawing sharper than that would just spend more fill-rate for a visually identical blurred result. Each blob orbits its own home point on an ellipse with its own independent speed and phase offset, so five simple sine/cosine motions combine into drift that never visibly repeats.
Best for: SaaS marketing hero sections and app onboarding screens wanting a trendy, colorful animated backdrop with near-zero JS cost. Tip: the whole effect works unchanged in React, Vue, or Angular — the CSS blur needs no lifecycle wiring at all; only the canvas ref and animation loop need a mount effect.
Grab the code: Canvas Mesh Gradient Background
How to drop these into your project
- Open any snippet and hit View / Edit Code to see the HTML, CSS and JS in separate tabs, then paste the HTML into your markup, the CSS into your stylesheet, and the JS before your closing
</body>tag — or use the one-click export to React, Vue, Angular or Tailwind right from the snippet page. Every snippet in this batch needs nothing installed — no CDN script, no npm package, pure Canvas 2D and vanilla JS. - Recursion can replace a data structure when the call stack already has what you need. The fractal tree and the lightning bolt both use their recursion depth for more than just stopping the recursion — depth doubles as the input to color, width, and displacement budget, so there's no second pass needed to add those details afterward.
- Position-based physics (Verlet) beats force-based physics for anything with rigid constraints. If you're building a rope, cloth, or chain, store current and previous position instead of velocity — deriving velocity implicitly makes an iterative distance-constraint solver almost trivial, which a spring-force model fights the whole way.
- A real force formula still needs a stability safeguard near its singularity. Any inverse-square (or inverse-distance) calculation blows up as distance approaches zero — add a small constant before dividing (force softening) rather than special-casing close approaches with a separate collision check.
- Let CSS do the parts CSS is actually good at. The mesh gradient background's blur and the pixelate reveal's nearest-neighbor upscale both lean on a single browser-native property (
filter: blur(),imageSmoothingEnabled) instead of hand-rolling the equivalent pixel math in JavaScript — cheaper, simpler, and usually GPU-accelerated for free.
Final thought
What connects a fractal tree, a Verlet rope, and a mesh gradient isn't a shared visual style — they don't look anything alike. It's that each one reaches for the real underlying technique (recursion, position-based integration, an inverse-square force law, gradient noise) rather than faking its silhouette with a canned animation. That's what makes the code worth reading even when you're not going to ship the exact effect: the midpoint-displacement function behind the lightning bolt is the same one that would generate a coastline; the constraint solver behind the rope is the same one that would build a cloth grid. Learn one of these honestly and two or three neighboring effects come along with it for free.
Try them, retune the constants, and export to your framework of choice in one click. Browse the full collection at FWD Tools UI Snippets — it's free and runs entirely in your browser.