Atmosphere✨ Premium

Wave Form

Continuously animated SVG wave via dual harmonic synthesis: two sine curves at offset frequencies, recomputed frame by frame via requestAnimationFrame.

SVGSmooth

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Atmosphere has 57 effects, including 10 free. Explore the category →

3 usage examples

Hero / Landing — SaaS signal line background — Wave Form example 1

① Hero / Landing — SaaS signal line background

WhenBehind a hero section or dashboard home page, when you want to convey a 'live' feel without visual distraction.
WhyThe animated wave suggests real-time measurement and positions the product in a tech/data register without overwhelming the main text.
SettingsNative amplitudes (30 + 15), speeds 0.005 / 0.003; gradient #6366f1 → #d946ef → #06b6d4 horizontal; stroke-width: 3; .wave-form height: 120px as a semi-transparent overlay beneath the text.
Podcast player — Wave as audio signature — Wave Form example 2

② Podcast player — Wave as audio signature

WhenInside a podcast, audiobook, or music track player, to visually convey the sound currently playing.
WhyThe animated SVG wave is the natural representation of an audio signal: it distinguishes the 'playing' state without canvas or Web Audio API, and adapts to any player width.
SettingsPrimary amplitude 25, secondary 12; speeds 0.005 / 0.003; gradient #7c3aed → #d946ef → #ec4899; stroke-width: 2.5; .wave-form height: 64px.
Conversion micro-interaction — Animated divider before pricing block — Wave Form example 3

③ Conversion micro-interaction — Animated divider before pricing block

WhenBetween the features block and the pricing block on a pricing page, to draw the eye to the CTA without interfering with reading.
WhyAn animated divider breaks the reading pattern and naturally guides the eye toward the offer below, without needing an image or video.
SettingsReduced speeds (0.002 / 0.001) to avoid distraction; primary amplitude 12, secondary 6; amber gradient #f59e0b → #ef4444; stroke-width: 2; .wave-form height: 48px.

How it works

The effect redraws the SVG path on every frame: animateWaveForm(time) builds a string of L commands from x=0 to x=300 (step 5 px, 61 points) and writes the result via wavePath.setAttribute('d', d). Unlike CSS animation or canvas, this is direct DOM manipulation — the browser repaints the <path> without creating a new element or allocating a buffer.

The shape is the superposition of two sine waves: a primary one (amplitude 30 px, spatial frequency 0.05 rad/px, temporal speed 0.005 rad/ms) and a slower, wider secondary one (amplitude 15 px, frequency 0.02, speed 0.003). Each wave's phase advances with time × speed (time = rAF timestamp in ms), creating the illusion of continuous rightward scrolling without any explicit loop.

The SVG uses viewBox="0 0 300 100" and preserveAspectRatio="none": the wave stretches to fill any container width without additional JS. The stroke color is stroke: url(#waveGradient) in the CSS — the gradient definition is absent from the native HTML and must be added manually inside a <defs> block within the <svg> for the path to be visible.

The requestAnimationFrame loop is shared with other page effects (audio visualizer, matrix rain…): animateWaveForm is one of ten calls in a central animate(time) function. No IntersectionObserver or pause mechanism is implemented — the RAF runs continuously even when the element is off-screen.

Accessibility

  • prefers-reduced-motion not supported: the animation runs in the main RAF loop without checking the system preference — implement manually if needed.
  • The <svg> has no aria-hidden attribute: screen readers traverse it even when the content is purely decorative. Add aria-hidden="true" on the <svg> for decorative use.
  • The .wave-form container has neither role="img" nor aria-label — add these if the wave carries semantic information (e.g. a data curve).
  • No keyboard or pointer interaction: the effect is passive, no tabindex or event handler is attached.
  • The stroke color references url(#waveGradient) which is absent from the HTML: the path may be invisible without the <defs> block — this gives an empty background but causes no errors or accessibility issues.

Browser compatibility

Requires SVG 1.1 (path + linearGradient) and requestAnimationFrame — natively supported in all modern browsers. Zero external dependencies.

Chrome 80+✓ Full
Firefox 75+✓ Full
Safari 13+✓ Full
Edge 80+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

If SVG is not rendered or the gradient is not defined, the <code>.wave-form</code> container stays empty with no JS error — the page remains functional.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="demo-preview">
  <div class="wave-form" id="waveForm">
    <svg viewBox="0 0 300 100" preserveAspectRatio="none">
      <!-- gradient absent from native code: add to make the stroke visible -->
      <defs>
        <linearGradient id="waveGradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%"   stop-color="#6366f1"/>
          <stop offset="50%"  stop-color="#d946ef"/>
          <stop offset="100%" stop-color="#06b6d4"/>
        </linearGradient>
      </defs>
      <path id="wavePath"></path>
    </svg>
  </div>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
url(#waveGradient) — SVG defs not defined in native HTML Add <defs><linearGradient id="waveGradient">…</linearGradient></defs> inside the <svg> before the <path> — without it the stroke is invisible.
stroke-width (CSS .wave-form path) 3 Stroke thickness in viewBox px. 1–2 for a subtle watermark; 5–8 for a graphic fill.
stroke-linecap (CSS .wave-form path) round End-cap style: butt (flush square), square (protruding square), round (rounded). Affects visual smoothness at the path ends.
Primary amplitude: 30 (JS animateWaveForm) 30 Main wave height in viewBox units (0–100). Lower to 10–15 for a subtle background; raise to 40 for a pronounced wave touching the edges.
Secondary amplitude: 15 (JS animateWaveForm) 15 Height of the superimposed slow oscillation. Set to 0 for a pure sine; match the primary amplitude for a more complex trace.
Primary temporal speed: 0.005 (JS time * 0.005) 0.005 Main wave scroll speed (rad/ms). 0.002 = slow and calming; 0.01 = fast and energetic.
Secondary temporal speed: 0.003 (JS time * 0.003) 0.003 Low-frequency drift speed. Keep lower than the primary speed for a natural, organic motion.
Spatial step: 5 (JS for x += 5) 5 Point density along the path. Reduce to 2 for a smoother curve (more DOM updates); increase to 10 to lighten fast animations.

FAQ

The CSS writes stroke: url(#waveGradient) but the <linearGradient id="waveGradient"> is not included in the JSON's HTML. Without a <defs> block in the SVG, the browser can't resolve the color and doesn't render the stroke. Add <defs><linearGradient id="waveGradient" x1="0%" x2="100%"><stop offset="0%" stop-color="#6366f1"/><stop offset="100%" stop-color="#06b6d4"/></linearGradient></defs> inside the <svg> before the <path>.
animateWaveForm targets document.getElementById('wavePath') — a single element. For multiple curves, duplicate the <path> with distinct IDs (wavePath2, etc.), create a variant of the function for each ID, and call all variants from the existing requestAnimationFrame loop. Vary amplitudes and speeds to visually distinguish each channel.
Yes, by adapting the gradient. On a white or very light background, choose dark saturated hues: #1e3a8a → #7c3aed → #0f766e for example. Avoid pastels close to white — SVG transparency provides no built-in backing. Also set stroke-width: 2 minimum to maintain legibility.