What this guide covers
In Part 1, I covered why mathematical animation is replacing stock photography and introduced the three-tier framework for choosing the right complexity level. This article is the practical companion — every formula family worth knowing, the tools that emerged in 2024–2025, and production-ready patterns you can drop into real projects.
This guide is designed to stand on its own. You don't need to read Part 1 first, but if you want the business context and strategic framework, it's there.
Three tiers in practice: implementation deep dive
Each complexity tier comes with its own trade-offs in performance, interactivity, and engineering effort. Here's what each one actually looks like in code.
Simple tier: Pure CSS trigonometric animations
Modern CSS natively supports trigonometric functions: sin(), cos(), tan(), asin(), acos(), atan(), and atan2(). These reached baseline support across all major browsers — Chrome 111+, Firefox 108+, Safari 15.4+, Edge 111+ — making them production-safe for any project today.
Combined with the @property rule for animatable custom properties and calc() for complex expressions, you can create genuine trigonometric orbit animations, wave movements, and parametric positioning entirely without JavaScript.
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.floating-element {
animation: cosmic-drift 8s linear infinite;
transform:
translateX(calc(sin(var(--angle)) * 80px))
translateY(calc(cos(var(--angle) * 1.3) * 50px))
rotate(calc(sin(var(--angle) * 0.7) * 8deg));
opacity: calc(0.6 + sin(var(--angle) * 0.5) * 0.3);
}
@keyframes cosmic-drift {
to { --angle: 360deg; }
}The key insight: multiplying --angle by different non-integer factors (1.3, 0.7, 0.5) within the same element creates a Lissajous-like compound motion. The element traces an irregular, never-quite-repeating path that reads as natural movement rather than mechanical rotation.
Performance reality: 60fps on all devices including 3-year-old budget phones. Zero main thread impact. Negligible battery drain. Memory under 10MB. You can animate 50+ elements simultaneously because these run entirely on the browser's compositor thread.
Medium tier: p5.js and Canvas API
When you need interactivity — response to mouse position, scroll depth, or a system of hundreds to thousands of particles — p5.js is the most accessible entry point. Its version 2.0, released in April 2025, was the biggest update since the library's creation in 2013.
The headline feature is p5.strands — a system that lets developers write GPU shaders in JavaScript instead of GLSL. This collapses what was a steep learning curve into something any web developer can approach.
let particles = [];
const PARTICLE_COUNT = 3000;
const NOISE_SCALE = 0.005;
function setup() {
createCanvas(windowWidth, windowHeight);
colorMode(HSB, 360, 100, 100, 100);
for (let i = 0; i < PARTICLE_COUNT; i++) {
particles.push({
x: random(width), y: random(height),
prevX: 0, prevY: 0,
speed: random(1, 3),
hue: random(180, 260)
});
}
background(15, 20, 10);
}
function draw() {
fill(15, 20, 10, 5);
noStroke();
rect(0, 0, width, height);
let t = frameCount * 0.002;
for (let p of particles) {
p.prevX = p.x;
p.prevY = p.y;
// The core: noise → angle → movement
let angle = noise(p.x * NOISE_SCALE, p.y * NOISE_SCALE, t)
* TWO_PI * 2;
p.x += cos(angle) * p.speed;
p.y += sin(angle) * p.speed;
// Wrap edges
if (p.x < 0) p.x = width;
if (p.x > width) p.x = 0;
if (p.y < 0) p.y = height;
if (p.y > height) p.y = 0;
let d = dist(p.x, p.y, mouseX, mouseY);
let alpha = map(d, 0, 300, 60, 15);
stroke(p.hue, 60, 85, alpha);
strokeWeight(1);
line(p.prevX, p.prevY, p.x, p.y);
}
}The formula at the core is simple: noise(x, y, t) → angle → cos/sin → movement. From this one operation, 3,000 particles create an organic, flowing visual that responds to time and mouse position. Changing NOISE_SCALE from 0.005 to 0.002 produces long sweeping curves; 0.02 produces turbulent chaos.
Performance profile: 30–60fps on desktop, 15–30fps on mobile. Memory: 10–100MB depending on particle count. Critical optimizations include object pooling, implementing prefers-reduced-motion, and throttling to 30fps on mobile.
Complex tier: WebGL/GLSL shaders
For hero sections that need to command attention, fractal explorers, or 3D mathematical surfaces — GPU shaders are non-negotiable. A fragment shader transforms a mathematical formula directly into pixels, with the GPU executing the computation for millions of pixels in parallel.
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution)
/ min(u_resolution.x, u_resolution.y);
// Animated zoom into Seahorse Valley
float zoom = pow(2.0, -u_time * 0.3);
vec2 center = vec2(-0.745, 0.186);
vec2 c = center + uv * zoom;
vec2 z = vec2(0.0);
int maxIter = 256;
int iter;
for (iter = 0; iter < maxIter; iter++) {
z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c;
if (dot(z, z) > 4.0) break;
}
float t = float(iter) / float(maxIter);
if (iter < maxIter) {
float sl = t - log2(log2(dot(z,z))) + 4.0;
t = sl / float(maxIter);
}
vec3 color = 0.5 + 0.5 * cos(
3.0 + t * 6.28 + vec3(0.0, 0.6, 1.0)
);
if (iter == maxIter) color = vec3(0.0);
gl_FragColor = vec4(color, 1.0);
}This shader runs at 60fps on any device with a discrete GPU. The mathematical formula is just z = z² + c — iterated until escape or maximum iterations — but the GPU evaluates it independently for every pixel on screen, in parallel. At 1920x1080, that's over 2 million simultaneous computations per frame.
The formula catalog
Mathematics offers an infinite library of visual forms. Here are the seven formula families I use most frequently, organized by visual character and design application. Each one can be implemented at any of the three tiers above.
Trigonometric waves — the foundation
Formula: y = A · sin(ωx + φ + vt)
A single sine wave creates undulating motion — ocean surfaces, audio visualizer aesthetics, breathing indicators. But the real power is composition. Combining two frequencies close together produces beat frequency interference — a pulsing amplitude modulation that feels organic, as if the animation has a heartbeat.
Use for: section dividers, loading states, audio visualization, ambient background movement.
Lissajous curves — mathematical elegance
Formula: x = A·sin(at + δ), y = B·sin(bt)
The visual character depends entirely on the ratio a/b. Rational ratios produce closed curves: 1:2 (figure-8), 3:2 (trefoil knot), 5:4 (star pattern). Irrational ratios like √2 mean the curve never closes — it progressively fills space, creating an evolving, never-repeating drawing.
Use for: logo animations, cursor trails, decorative motion glyphs, loading spinners.
Perlin noise flow fields — organic streaming
Formula: angle(x,y) = noise(x·scale, y·scale, t) · 2π
Invisible force fields made visible. Thousands of particles follow noise-derived vectors, creating patterns that evoke wind, water, or migration. Fractal Brownian Motion is simply layered noise at increasing frequencies and decreasing amplitudes — the mathematical core behind the Stripe gradient.
Use for: hero backgrounds, ambient textures, generative art, data visualization metaphors.
Mandelbrot and Julia fractals — infinite detail
Formula: z(n+1) = z(n)² + c
Infinite detail at every zoom level. Animated zoom into Seahorse Valley produces a journey that can run for hours without repeating. Julia sets — the same formula with fixed c — create mesmerizing morphing effects when c is animated along a path.
Use for: hero sections, exploration interfaces, infinite zoom experiences, generative identity systems.
Fibonacci phyllotaxis — nature's pattern
Formula: Point n at angle n · 137.508°, radius c · √n
The sunflower seed spiral. The golden angle (137.508°) ensures optimal packing, producing patterns instantly recognizable as natural even when rendered abstractly. Change the angle by 0.1° and the pattern collapses into visible spokes.
Use for: data displays, particle effects, organic scatter, nature-inspired layouts.
Strange attractors — deterministic chaos
Clifford: x(n+1) = sin(ay) + c·cos(ax), y(n+1) = sin(bx) + d·cos(by)
Four parameters control infinite variety. Pre-computing 80,000 points and progressively revealing them creates an "emergence" effect — watching structure materialize from apparent randomness. Each parameter set produces a completely different visual signature.
Use for: generative brand identity, unique visual fingerprints, artistic hero sections, loading experiences.
Superformula — one formula, infinite shapes
Formula: r(θ) = (|cos(mθ/4)/a|^n₂ + |sin(mθ/4)/b|^n₃)^(-1/n₁)
Adjust parameters to get circles, stars, organic blobs, crosses, flowers, or biological cell shapes. Animating parameters creates continuous morphing — one element transforming endlessly. This single formula can replace an entire library of SVG icons with a parametric shape engine.
Use for: morphing logos, parametric icons, organic shape transitions, generative patterns.
Interactive superformula explorer — coming soon
The Stripe gradient: FBM in production
I covered the full four-layer Stripe gradient breakdown in Part 1. The core technique is Fractal Brownian Motion — six octaves of noise stacked with a rotation matrix between octaves to break grid alignment. Here's the FBM function for reference:
float fbm(vec2 p) {
float v = 0.0, a = 0.5;
mat2 rot = mat2(cos(0.5), sin(0.5),
-sin(0.5), cos(0.5));
for (int i = 0; i < 6; i++) {
v += a * noise(p);
p = rot * p * 2.0;
a *= 0.5;
}
return v;
}The 2024–2025 tools most developers haven't discovered
TypeGPU — TypeScript shaders with full type safety
Created by Software Mansion. Write WebGPU shaders entirely in TypeScript with end-to-end type safety from CPU to GPU. Automatic byte alignment, shader compilation from TypeScript, Three.js integration from v0.9.0, React Native support via react-native-wgpu.
Use when: you need type-safe WebGPU in a TypeScript codebase. Skip when: quick prototyping — the setup overhead doesn't pay off for throwaway experiments.
ralph-gpu — WebGPU in one function call
From Vercel Labs. Write a WGSL fragment shader, call .draw(). Auto-injects uniforms for resolution, time, delta time, frame count, and aspect ratio. First-class ping-pong buffer support for fluid simulations.
Use when: rapid shader prototyping or one-off visual effects. Skip when: you need complex scene graphs or 3D — it's 2D fragment shaders only.
POINTS — WebGPU-native generative art
Built entirely on WebGPU with built-in shader modules for noise, signed distance functions, color manipulation, and mathematical effects. 2,398+ commits, actively maintained. The first WebGPU-native creative coding framework.
Use when: building generative art or creative coding projects targeting WebGPU. Skip when: you need broad browser support today — WebGPU isn't universal yet.
Mafs — React components for math visualization
~4,000+ GitHub stars. Opinionated React components for interactive 2D math: coordinate planes, function plots, vectors, parametric curves, drag interactions.
Use when: you need a math visualization in React that looks great immediately. Skip when: you need custom rendering or 3D — it's specifically 2D educational/documentation math.
The WebGPU milestone
WebGPU reached a critical milestone: all major browsers now ship it by default, covering roughly 70% of desktop users. Chrome and Edge since 2023, Firefox 141 on Windows (July 2025), Firefox 145 on macOS (Apple Silicon only), Safari 26 in macOS Tahoe — enabled by default, not experimental. Linux and Android remain in progress, so mobile coverage is still lower.
The performance gains are transformative. A particle system running 10,000 particles at 30ms per frame via WebGL handles 100,000 particles in under 2ms with WebGPU compute shaders — roughly 150x improvement.
Three patterns worth stealing
Every technique above can be distilled into a minimal, production-ready pattern. Three combinations that work as drop-in design elements — each constrained to a single color, generous negative space, and under 40 lines of canvas code.
Waveform Divider
Replace static ‹hr› with breathing sine interference. Five overlapping frequencies, white only, opacity 6–18%.
Ambient Texture
Noise-driven pixel field as a living surface. One hue, near-invisible — adds depth without competing with content.
Motion Glyph
A 3:2 Lissajous trace as an animated accent mark. Single curve, fading trail — a living decorative element.
Performance, accessibility, and Core Web Vitals
Mathematical animations must coexist with Google's Core Web Vitals: LCP under 2.5 seconds, INP under 200ms, CLS under 0.1. Sites passing all three consistently see lower bounce rates. Here's how to get there.
Loading strategy
Heavy libraries loaded synchronously block rendering. Three.js: ~150KB gzipped. p5.js: ~300KB. Code-split animation code out of the critical path, use async/defer on script tags, and never make the animated canvas the Largest Contentful Paint element.
Viewport lifecycle management
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) animation.loop();
else animation.noLoop();
});
}, { threshold: 0.1 });
observer.observe(document.querySelector('canvas'));Adaptive quality detection
function getQualityTier() {
const cores = navigator.hardwareConcurrency || 4;
const memory = navigator.deviceMemory || 4;
const isMobile = window.innerWidth < 768;
if (isMobile || cores <= 2 || memory <= 2) return 'low';
if (cores <= 4 || memory <= 4) return 'medium';
return 'high';
}
const qualityMultipliers = {
low: 0.25, medium: 0.5, high: 1.0
};
const particleCount = Math.floor(
5000 * qualityMultipliers[getQualityTier()]
);This gives you 1,250 particles on a budget phone, 2,500 on a mid-range device, and the full 5,000 on a desktop.
Accessibility is non-negotiable
prefers-reduced-motion must be respected — not by eliminating motion, but by replacing pulsing with gentle fading and slowing transitions. WCAG 2.2.2 (AA): provide a mechanism to pause animations lasting 5+ seconds. WCAG 2.3.1: no content flashing more than 3 times per second.
What's next: AI, real-time data, and WebGPU compute
AI-assisted creative coding can already generate working p5.js sketches, GLSL shaders, and CSS animations from natural language. The barrier to a first draft is near zero. But the barrier to a production-quality result — performant, accessible, mathematically refined — remains high. AI generates code that compiles; human judgment shapes code that impresses.
Real-time data integration turns animation into ambient communication. Dashboard backgrounds driven by live metrics — pulse faster when traffic spikes, shift color based on revenue trends, particle density mapping to user activity.
WebGPU compute shaders unlock previously impossible browser simulations: millions of particles with inter-particle forces, fluid dynamics, cloth simulation, real-time procedural terrain — all at 60fps in a browser tab.
Production checklist
Before shipping any mathematical animation, verify:
Performance
- Animation doesn't block Largest Contentful Paint
- Scripts loaded with
asyncordefer - Intersection Observer starts/stops based on viewport visibility
- Frame rate throttled to 30fps on mobile
- Tab visibility API pauses animation when hidden
- Particle counts adapt to device capability
Accessibility
prefers-reduced-motionreduces or pauses animation- Pause mechanism available for animations longer than 5 seconds
- No content flashes more than 3 times per second
- Canvas elements have appropriate
aria-hiddenoraria-label - Animation doesn't interfere with screen reader navigation
Quality
- Animation communicates brand values, not just visual noise
- Seeded randomness enables reproducible, shareable states
- Fallback exists for devices without WebGL/WebGPU support
- Colors work in both light and dark contexts
- Animation degrades gracefully on low-end devices
Start with one formula, ship it, then iterate
You don't need seven formula families to ship something impressive. Pick one — a CSS sine wave divider, a canvas flow field, or a GLSL fractal hero. Get it running, measure the Core Web Vitals impact, and iterate from there.
The formulas aren't going anywhere. The tools keep getting better. The only variable is when you start.
If you want the strategic framework — why this matters for business, the cost breakdown, and the ROI case — read Part 1: How Mathematical Animation Is Replacing Stock Photography.
Ready to implement mathematical animation in your next project? Let's discuss which formulas and tools fit your goals.