motion-background
This skill should be used when the user asks to "add an animated background", "build a mesh/gradient background", "make an aurora/shader background", "add constellation/particle background", "animated hero background", or "a subtle looping background behind content". Covers CSS mesh gradients, GLSL
By iart-ai · 767 installs
npx skills add iart-ai/motion-design-skills --skill motion-background
Source repository · Upstream listing
Motion Background
Ambient, living backgrounds that sit behind content without stealing focus. The goal is subtle, seamlessly looping motion that stays readable and performant. This skill is self contained: every technique below ships its own runnable code — CSS, GLSL, and canvas — with no external dependencies beyond Three.js where a shader is involved.
When to use
Hero/landing background that subtly moves; section ambience.
Login/splash/empty state living backdrops.
A gradient, mesh, aurora, shader, or particle/constellation field behind text or UI.
Pick an approach
Look Technique Cost
Soft animated gradient/mesh CSS gradients + keyframes Cheapest, no JS
Flowing aurora / organic noise GLSL fragment shader (Three.js full screen quad) GPU, moderate
Constellation / drifting dots Canvas 2D particles CPU, scales with count
Depth / parallax Same shader/particles with mouse driven offset Moderate
Default to CSS if a gradient suffices — it is the cheapest and most reliable. Use a shader for organic flowing color; use canvas particles for a constellation/network look.
Design rules
Subtle : low contrast versus content, slow motion (long periods, 8–30s loops), nothing that competes with text.
Readable : keep contrast for foreground text; add a scrim ( linear gradient overlay or backdrop ) if needed.
Seamless loop : drive motion with periodic functions so time wraps with no visible jump (see below).
Respect motion preferences and battery : honor prefers reduced motion , and pause when offscreen or the tab is hidden.
Core techniques (inlined, runnable)
1. Animated CSS mesh gradient (no JS)
Layered radial gradients whose positions drift. Animating background position on a larger than viewport gradient loops seamlessly.
The 0% and 100% keyframes are identical, so the loop has no seam.
2. Full screen GLSL gradient + noise shader (Three.js)
A flowing aurora/gradient using value noise in a fragment shader on a full screen plane. uTime advances each frame; to loop, feed it a wrapped time (section 4).
3. Canvas constellation particles
Drifting points connected by lines when near — the classic "network" background. Pure canvas 2D, no dependencies.
The O(n²) link loop is fine to ~120 points; above that, spatial hash into a grid and only test neighboring cells.
4. Seamless loop technique
For canvas/JS, wrap time into a fixed period so motion repeats exactly. Use the loop phase (0→2π) as the argument to periodic functions:
Any motion built only from sin / cos of phase (or integer multiples) loops seamlessly. In the shader, feed uTime = phase and use only sin / cos of it; for noise scrolled gradients, scroll by an integer number of noise cells per period so the field tiles.
5. Reduced motion + offscreen/hidden pause
When running is false, skip the render inside the rAF loop (as in section 2) — the loop stays alive to resume cheaply, but does no GPU/CPU work.
Deliver & verify (standalone HTML)
Packaged helper ( scripts/ ): scripts/seek shot.sh anim.html 0 1.5 3 freezes the ?t=N harness and screenshots each moment; scripts/contact sheet.sh sheet.png frame .png tiles them for one glance review. See scripts/README.md .
A motion background ships as one .html file that opens directly in a browser — markup, the background, and (for shader/canvas) Three.js or canvas JS from CDN, all inline. One file is the right tier.
Output contract:
One .html file: the background layer + a sample of foreground text on top to check readability/contrast.
One animation driver — the CSS @keyframes , the shader rAF loop, or the canvas rAF loop; just one.
Include the freeze harness below, matched to the technique, so any moment can be screenshotted deterministically.
Freeze harness — pin a frame for screenshots. Match the mechanism to the technique:
Verify loop — render → freeze → screenshot → check:
1. Open the file frozen at start / mid / end across one loop period: …/bg.html?t=0 , ?t=<period/2 , ?t=<period .
2. Screenshot each frozen frame.
3. Check fidelity (subtle, on brand, seamless) and artifacts — text contrast holds at every frame, no banding in gradients/shader, the loop seam ( t=0 vs t=period ) matches, no GPU/console errors.
Before you finish:
1. Opens standalone in a browser — no console/WebGL errors, no missing CDN.
2. One driver; ?t=N freezes the exact frame (shader renders one frame, canvas sim stepped deterministically).
3. Screenshotted at start / mid / end — foreground text stays readable, no banding, loop seam invisible.
4. prefers reduced motion honored (one static frame rendered, loop stopped) + pauses offscreen/hidden.
5. devicePixelRatio capped at 2; motion is slow and subtle, never out contrasting content.
Quick reference
Need Do
Cheapest gradient CSS layered radial gradient + background position keyframes
Organic flow GLSL fbm noise, scroll uTime
Network/dots canvas particles + distance linked lines
No seam drive motion by sin/cos(phase) , identical first/last keyframe
Perf cap setPixelRatio(min(dpr, 2)) , throttle, reduce particle count on mobile
Accessibility prefers reduced motion static fallback
Save battery pause on visibilitychange + IntersectionObserver
Gotchas
Never let the background out contrast the foreground text — add a scrim if it does.
Uncapped devicePixelRatio on retina/4K murders the GPU; cap at 2.
background position loops only if first and last keyframes match exactly.
Noise scrolled shaders loop only if the scroll is an integer number of cells per period; otherwise the loop visibly jumps.
Forgetting the offscreen/hidden pause drains battery on mobile even when the user can't see it.
Reference files
references/background recipes.md — fuller drop in implementations: a richer multi blob CSS mesh with blur, the complete Three.js aurora shader with mouse parallax and a true seamless loop time wrap, a grid optimized constellation field with mouse repulsion, a perfectly looping noise flow technique, and a complete reduced motion + offscreen pause manager wrapping all of them.