Built on the open web

Every browser API and CSS feature the player calls, and what each one is for. A music player touches a lot of them, which is part of the point.

Media

  • HTMLMediaElementOne audio and one video element for the whole page, which every control drives.
  • TimeRangesShows how much of the file is loaded past the playhead.
  • Screen Wake LockKeeps the screen on while a video plays in Now Playing, and only then.
  • VibrationA short tick under the thumb on play and pause.
  • Network InformationRespects Data Saver by fetching nothing before a press.
  • Media SessionGives the lock screen and headphones the track's title, artwork and controls.
  • Remote PlaybackShows the cast button only when a Chromecast or AirPlay target is in reach.
  • Web AudioReads the signal that lights the filament.
  • AnalyserNodeTurns the signal into one heat value and three band levels, every frame.
  • Page VisibilityMoves a playing video to audio when the page goes to the background.
  • Lazy loadingFetches list thumbnails only as they scroll into view.
  • Async decodingDecodes cover art off the main thread so the seek line does not stutter.

Interface

  • Pointer EventsOne gesture helper for swiping the bar and dragging the sheets.
  • Web AnimationsBreathes the filament where there is no signal to follow.
  • requestAnimationFrameMoves the seek line and the filament every frame, not four times a second.
  • Web ShareOpens the system share sheet with the track's title and the post link.
  • ClipboardCopies the link where there is no share sheet.
  • inertMakes Now Playing a real modal: nothing behind it can take focus.
  • matchMediaReads the same breakpoint and motion preference the stylesheet uses.
  • scrollIntoViewBrings the playing track into view when Up next opens.

Platform

  • ES modulesThe shipped file is the source, loaded as a module with no build step.
  • Dynamic importLoads the Listen app only on the page that holds the block.
  • HistoryBack closes Now Playing, and the Listen app navigates without a page load.
  • Web StorageCarries the queue and position to the next page, and remembers the volume.
  • FetchSwaps library views in from the REST route without a page load.
  • Navigation TimingTells a reload from a link, so a reload never autoplays.
  • pagehideCaptures the exact position when the listener leaves the page.
  • pageshowRestarts the frame loop after a Back from the back-forward cache.
  • ARIA dialogNow Playing is a named modal dialog with Escape and focus return.

Styling

  • @propertyRegisters the filament's heat as a real number, so it can animate.
  • color-mix()Tints rows, pills and the seek line from the theme's own text colour.
  • oklabMixes the filament's colour from red through amber to white without muddy midtones.
  • Container queriesSizes the cover from the stage it sits in, not the viewport.
  • :has()Styles a parent from a child's state, without the script toggling classes.
  • env() safe areasKeeps the bar and Now Playing clear of the notch and the home indicator.
  • text-wrapBalances a long title in the Listen app so no word is left alone.
  • Variable fontsShips each font as one file covering every weight the player asks for.

Behaviour

  • prefers-reduced-motionStops the equalizer, the filament and the sliding sheets when the system asks.
  • prefers-reduced-transparencyRemoves the translucent wash and the bloom when the system asks.
  • clip-pathHides the Song and Video labels on a phone, but not from screen readers.
  • aspect-ratioReserves the video's box and each record cover's square before anything loads.
  • accent-colorRecolours the browser's own volume slider to the player's white.
  • touch-actionClaims the swipes and drags so the browser does not scroll instead.
  • overscroll-behaviorKeeps the Up next list's scroll from moving the post behind it.
  • :focus-visibleShows a focus ring for the keyboard and not after a tap.