Twenty runnable JavaScript animations - galaxy particles, matrix rain, three.js bloom, CSS 3D - with a live editor. Change the code, see it instantly, download the HTML.
Every animation here ships as a complete HTML, CSS and JavaScript file. Pick one, edit any of the three panes, and the preview re-runs in under a second. Nothing is uploaded and nothing is compiled on a server - the code executes in a sandboxed frame inside your own browser.
The gallery covers the four ways animation actually gets done on the web:
requestAnimationFrame. Galaxy spirals, matrix rain, flow fields, fireworks, Verlet cloth, falling-sand automata.(uv, time).UnrealBloomPass post-processing.transform-style: preserve-3d, keyframes, @property-registered custom properties, and backdrop-filter. No canvas involved at all.Most animation demos you scroll past show you a result and a screenshot of a fragment. That teaches nothing, because animation is almost always one small idea repeated per frame:
Each demo is commented at exactly the line where that idea lives. Change the constant, hit Run, and watch what breaks.
console.log output and runtime errors from the sandbox, with line numbers relative to your JS pane.The demos labelled heavy push tens of thousands of points through the GPU. On an integrated graphics laptop, drop the count constant to a quarter of its value before assuming something is broken. Every demo caps devicePixelRatio at 2, because rendering a 3x retina buffer costs nine times the fill rate of a 1x one for no visible gain on a particle field.
Canvas 2D and CSS demos work everywhere. The WebGL and three.js demos need a working GPU context - if the preview stays black, check that hardware acceleration is enabled in your browser settings. The three.js demos fetch the library from jsDelivr, so they are the only ones that need a network connection after page load.
| Technique | Best at | Falls over when | Demos here |
|---|---|---|---|
| CSS keyframes / transitions | UI motion, hover states, anything the compositor can handle without JavaScript | You need per-particle logic or physics | Neon 3D Cube, Bouncy Clock, Folding Panel, Acid Glass |
| Canvas 2D | A few thousand independent shapes, trails, cellular automata, text rasterisation | Element counts pass roughly 10,000 per frame | Galaxy Spiral, Matrix Rain, Fireworks, Falling Sand, Character Cloth |
| Raw WebGL | Per-pixel effects where the whole image is a function of position and time | You want objects, cameras and lights rather than pixels | Plasma Shader |
| three.js | Scenes with tens of thousands of points, real 3D cameras, post-processing | A 600 KB dependency is too much for the payoff | three.js Galaxy, Particle Sphere, Holographic Card, Bloom Torus Knot, Shape Morph |
A useful rule: if the thing you are animating already exists as a DOM element and there are fewer than about fifty of them, use CSS. If you are drawing thousands of things that do not need to be clickable, use canvas. If every pixel needs its own calculation, use a shader.
1. The translucent wipe. Painting rgba(0,0,0,0.08) over the canvas instead of clearing it makes every previous frame decay. That single line is the entire trail effect in Matrix Rain, Flow Field and Spirograph Trails. Lower alpha means a longer trail.
2. Additive blending. Setting ctx.globalCompositeOperation = 'lighter' (or THREE.AdditiveBlending) makes overlapping particles sum their brightness instead of covering each other. It is why particle clouds glow at the centre without any lighting calculation.
3. Randomness raised to a power. Math.pow(Math.random(), 3) is still between 0 and 1, but heavily biased toward 0. Multiply it by a spread and you get scatter that clusters tightly near the origin with rare far outliers - which is what makes galaxy arms look like arms rather than a smear. That randomnessPower constant appears in both galaxy demos.
4. Verlet integration. Store a point's previous position instead of its velocity. Velocity is then just current - previous, and you enforce constraints by moving points directly, with the physics correcting itself on the next frame. Character Cloth and Cursor Creature are the same twenty lines with different constraints.
5. Time as the only input. In the Plasma Shader nothing is stored between frames at all: the colour of every pixel is computed from its coordinates and the clock. That statelessness is why shaders parallelise perfectly across thousands of GPU cores, and why the same technique scales to full-screen 4K where a canvas loop would not.
No. The editor and the preview both run entirely in your browser. Your code is executed inside a sandboxed iframe on an opaque origin, which means it cannot read this page, your cookies, or your storage - and it is never transmitted to a server. The Share button encodes the code into the URL itself rather than saving it anywhere.
Yes. Every demo is plain HTML, CSS and JavaScript with no license strings attached - use them, edit them, ship them. Click Download .html to get a single self-contained file that runs by double-clicking it. The three.js demos additionally load three.js from a CDN, which is MIT licensed.
No. The preview declares an import map that resolves the bare specifier three to a CDN copy, which is why the demos can write import * as THREE from 'three' with no bundler. If you download a demo, the same import map ships inside the file, so it keeps working offline-free from disk as long as you have a network connection.
Almost always one of three things: a JavaScript error (open the Console panel - errors show there with a line number), a WebGL context that could not be created (check that hardware acceleration is on in your browser), or an animation that draws off-screen after you changed a coordinate. Hit Reset to restore the original demo and work forward from there.
Canvas 2D gives you an immediate-mode drawing API - you clear and repaint every frame on the CPU, which is simple and flexible up to a few thousand shapes. WebGL runs your code on the GPU as shaders, so it scales to millions of pixels or points but requires writing GLSL. CSS animation is declarative: you describe the start and end state and the browser interpolates on the compositor thread, which is the cheapest option for UI motion but cannot express per-particle logic.
A canvas backing store scales with the square of the pixel ratio. On a 3x display an uncapped canvas renders nine times the pixels of a 1x one, which usually halves the frame rate for no perceptible gain on a particle field or a blurred glow. Capping at 2 is the standard compromise - text and thin lines still look sharp, but fill rate stays affordable.
Do not clear the canvas. Instead of clearRect, paint a translucent rectangle over the whole surface each frame - for example ctx.fillStyle = 'rgba(0,0,0,0.08)' followed by fillRect. Old pixels get darker every frame instead of vanishing, which reads as a fading trail. The alpha value controls the trail length: lower means longer. Matrix Rain, Flow Field and Spirograph Trails in this gallery all use exactly that trick.
Not automatically. requestAnimationFrame fires at the display refresh rate, so a fixed per-frame increment runs 1.7x faster on a 165 Hz monitor than a 60 Hz one. The three.js demos avoid this by multiplying motion by the clock delta. If you write your own, take a delta from performance.now() and scale by it rather than assuming 16.7 ms per frame.
Explore the Mandelbrot set in your browser - zoom, pan, tune iterations, switch to Julia sets, and save a PNG.
Draw spirograph and harmonograph figures in your browser. Adjust the frequency ratio, radii and damping, then save a PNG.
Generate the Matrix digital rain effect in your browser. Tune speed, glyphs, colour and trail length, then export a PNG, video or standalone HTML file.