webdevpuneet.com

Audio Buffering Visualizer — Equalizer Bars for Audio Loading States

Audio Buffering Visualizer · Loaders · Plain HTML, CSS & JS · Live preview

CategoryLoaders

Copy & paste

Source Code

<div class="ab-player">
  <div class="ab-art">♪</div>
  <div class="ab-info">
    <div class="ab-track">Midnight Static</div>
    <div class="ab-artist">Aurora Fields</div>
    <div class="ab-bars" id="abBars">
      <span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
    </div>
    <div class="ab-status" id="abStatus">Buffering…</div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Two distinct bar patterns
Buffering and playing use genuinely different keyframes, not a recolor.
Irregular buffering timing
Mismatched per-bar durations and delays make waiting feel tentative.
Confident playing motion
Taller, faster, evenly-timed swings once ready.
Real state transition
JS swaps classes and status text on an actual event, not a loop.
Audio-context styling
Album art, track/artist text, and a compact player shell.
Status label sync
The text label changes in step with the bar pattern.
Media-event ready
Structured to hook into real <audio> waiting/playing events.
Zero dependencies
Pure CSS keyframes plus a tiny JS class toggle.

About this UI Snippet

Audio Buffering Visualizer — A Waiting Pattern That Resolves Into Playback

Screenshot of the Audio Buffering Visualizer snippet rendered live

Audio players need a loading state that fits their context — an equalizer-style bar visual rather than a generic spinner, since bars already read as "sound" to anyone who's seen a music app. This snippet gives an audio player two distinct bar-animation states: a gentle, irregular "buffering" pattern while audio loads, and a confident, fuller-swing "playing" pattern once it's ready — deliberately different motions, not the same animation just recolored.

Two states, two different keyframes

Buffering uses abWait, a shallow oscillation between 20% and 45% height with each of the 8 bars given its own animation-delay (0.03s–0.22s) and its own animation-duration (0.9s–1.4s) — genuinely irregular per-bar timing rather than an evenly-staggered sequence, so the bars pulse somewhat chaotically, like they're waiting rather than performing. Once ready, abReady's abPlay keyframe swings each bar between 25% and a full 100% height on a snappier, uniform 0.7s cycle with tighter, evenly-spaced delays — a confident, rhythmic equalizer motion that reads as active music, not uncertainty.

Why irregular timing matters for "waiting"

Uniform timing (every bar identical except for a linear stagger) reads as controlled and purposeful — appropriate for playback, wrong for buffering. Giving buffering bars mismatched durations and delays that don't follow a clean sequence is what makes the pattern feel tentative and provisional, distinct from the wave loader's clean, evenly-staggered wave or the dots loader's wave variant — those communicate general-purpose "loading," while this specifically communicates "audio, buffering."

A real state transition, not a fixed animation

JavaScript adds the .ab-buffering class on load and, after a timeout standing in for the audio actually having buffered enough to play, swaps it for .ab-ready while updating the status label from "Buffering…" to "Now playing." In a real player you'd trigger that swap from the media element's own canplaythrough or waiting/playing events rather than a fixed delay.

Audio-specific, not video-shaped

Unlike a video buffering overlay (a full-frame spinner over the video canvas), this is built for an audio player's compact, persistent UI — album art, track/artist text, and inline equalizer bars that fit a mini-player or now-playing bar. Pair it with a music player shell or an audio waveform visualizer for a real, signal-driven playing state.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA mini music player renders with bars pulsing in the buffering pattern.
  2. 2
    Watch the buffering barsNotice each bar has its own timing — a gentle, irregular "waiting" motion.
  3. 3
    Wait for the transitionAfter ~2.6s the status changes to "Now playing" and the bars switch patterns.
  4. 4
    Compare the two motionsThe ready state swings taller and faster with tighter, uniform timing.
  5. 5
    Wire to real media eventsTrigger the class swap from your <audio> element's waiting/canplaythrough/playing events.
  6. 6
    Restyle the playerChange the album art gradient, bar colors, or bar count.

Real-world uses

Common Use Cases

Music player buffering
Replace a generic spinner with equalizer bars in a waiting rhythm, then switch to a confident playing pattern inside a music player.
Podcast and audiobook apps
Show buffering before playback starts, using irregular per-bar durations and delays so the wait reads as genuinely uncertain.
Voice message players
Give chat voice notes a compact loading state, where the same bars become taller and faster the moment audio is ready.
Live audio stream connecting
Indicate that a stream is connecting or rebuffering, with JavaScript swapping classes and status text on a real readiness event.
Motion design comparisons
Study how two distinct sets of keyframes make waiting and playing feel different, using only animation-delay and animation-duration.
Related: Skeleton-to-Content Crossfade
See the Skeleton-to-Content Crossfade for a related loaders pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

They use separate CSS keyframes: buffering (abWait) oscillates each bar in a shallow 20-45% height range with mismatched, non-sequential per-bar durations and delays, giving it an irregular, tentative feel. Playing (abPlay) swings bars in a much taller 25-100% range on a faster, uniform 0.7s cycle with evenly-spaced delays, reading as confident, rhythmic motion. They are genuinely different animations, not the same keyframe recolored or resized.

Uniform, evenly-staggered motion reads as controlled and purposeful, which is the wrong signal for "still loading, please wait." Giving each buffering bar its own slightly mismatched duration and delay — rather than a clean linear stagger — makes the motion feel provisional and uncertain, distinguishing it from a confident playback visualizer or a generic wave loader.

Listen for your <audio> or <video> element's waiting event to add the buffering class, and its canplaythrough or playing event to swap to the ready class — replace the fixed setTimeout with these real event listeners so the visual accurately reflects actual buffering state rather than a guessed delay.

A video buffering indicator is typically a full-frame spinner overlaid on the video canvas itself, since video has a large visual area to darken and overlay. This snippet is built for an audio player's compact, always-visible mini-UI — album art plus inline equalizer bars — which stays visible in a persistent now-playing bar rather than overlaying full-screen content.

Track a status state ('buffering' or 'ready') and derive the bars container's class from it, updating it inside your audio element's event handlers (onWaiting, onCanPlayThrough/onPlaying in React's <audio> props, or the equivalent native event listeners in Vue/Angular). The keyframes and per-bar delay/duration CSS need no changes.