DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

Spotify's Now-Playing Bar Is Just One CSS Grid + a Ticking Width

That player bar pinned to the bottom of Spotify looks like a polished component. Build it and it's a 3-column grid + two divs + a timer. Day 6 of my DesignFromZero series.

Three columns

.sp-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;  /* track · controls · volume */
  align-items: center;
}
Enter fullscreen mode Exit fullscreen mode

Left and right stretch; the centre is fixed — so the play button stays dead-centre at any width.

The progress bar is two divs

<div class="track"><div class="fill" style="width: 42%"></div></div>
Enter fullscreen mode Exit fullscreen mode

Outer = grey rail, inner width% = elapsed. Spotify's signature touch: the fill is white, turns green on hover, and a knob appears.

.track:hover .fill { background: #1db954; }
Enter fullscreen mode Exit fullscreen mode

"Playing" = a boolean + a 1-second timer

You don't need real audio to sell it. Hold elapsed seconds, tick every second, grow the fill:

let t = 0, playing = false;
setInterval(() => { if (playing && t < DUR) { t++; render(); } }, 1000);
playBtn.onclick = () => playing = !playing;
Enter fullscreen mode Exit fullscreen mode

Scrub with offsetX

track.onclick = e => { t = (e.offsetX / track.clientWidth) * DUR; };
Enter fullscreen mode Exit fullscreen mode

offsetX is the click position inside the rail; divide by width for a 0–1 fraction. One line gives click-to-seek.

Swap the fake timer for a real <audio> element's currentTime and it's a genuine player — the structure doesn't change.

🎵 See it live (hit play, scrub the bar): https://dev48v.infy.uk/design/day6-spotify-nowplaying.html

Day 6 of DesignFromZero.

Top comments (0)