Guides

Short, focused recipes. Built for shipping.

Hero background

Build a subtle, layered hero backdrop that stays performant.

Learn more

Scroll-reactive parallax

Tie wave amplitude and wavelength to scroll position.

Learn more

Audio-driven waves

Use WebAudio input to drive intensity and color.

Learn more

Quality presets

Balance memory and clarity for battery, balanced, and quality modes.

Learn more

Hero background

Atmosphere, not distraction.

const gen = new SineWaveGenerator({
  el: "#hero",
  autoResize: true,
  waves: [
    { amplitude: 16, wavelength: 220, speed: 0.6 },
    { amplitude: 10, wavelength: 160, speed: 0.4 }
  ]
});

gen.start();

Purpose

Give the page depth and calm motion without competing with copy.

Why it works

Two slow waves create parallax at low contrast. The eye reads the motion as atmosphere, not content.

How to apply

  • Keep amplitude under 20px to avoid stealing attention.
  • Use two wavelengths for depth (e.g., 220 + 160).
  • Lower stroke opacity to 0.15–0.4 for softness.
  • Set autoResize: true for responsive headers.
Learn more

Scroll-reactive parallax

Motion that tracks progress.

window.addEventListener("scroll", () => {
  const progress = scrollY / (docHeight - innerHeight);
  wave.amplitude = 10 + 30 * progress;
  wave.wavelength = 140 + 240 * (1 - progress);
});

Purpose

Let users “feel” progression without extra UI.

Why it works

Amplitude increases while wavelength tightens, so the motion intensifies naturally as users move through the page.

How to apply

  • Throttle updates with requestAnimationFrame.
  • Clamp progress to 0–1 for stable motion.
  • Use a reduced-motion fallback (slow or pause).
Learn more

Audio-driven waves

Sound in, motion out.

Idle
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 128;
// Map frequency bins to wave intensity.

Purpose

Turn audio energy into visual rhythm.

Why it works

FFT bins provide a stable amplitude envelope that maps cleanly to wave height and color.

How to apply

  • Start audio on a user gesture to satisfy mobile policies.
  • Normalize 0–255 data into 0–1 amplitudes.
  • Use light smoothing for natural motion.
Learn more

Quality presets

Fidelity when you want it. Battery when you need it.

Quality preset: balanced
gen.setQualityPreset("balanced");
gen.setQualityPreset("quality");
gen.setQualityPreset("battery");

Purpose

Keep visuals consistent across devices with one switch.

Why it works

Pixel ratio controls the render buffer size, which is the biggest cost driver for canvas memory and fill rate.

How to apply

  • Use balanced as the default.
  • Switch to battery on mobile or low power.
  • Offer quality for hero moments.
Learn more