audio-player
Platform audio player that wraps native <audio> with custom controls in shadow DOM. Progressive enhancement — native audio works without JS.
Overview
A platform-native audio player that wraps <audio> in light DOM and renders custom controls in shadow DOM. The native player is always the fallback — if JS is unavailable or the component fails, <audio controls> works normally.
Pair with <audio-visualizer> for canvas-based frequency or waveform visualization.
Single Track
Playlist Mode
Include a <details> with <ol class="track-list"> inside the component. Clicking a track updates the audio source and plays it.
Shuffle and Loop
Attributes
| Attribute | Type | Description |
|---|---|---|
autoplay | Boolean | Start playing on load (subject to browser autoplay policy) |
loop | Boolean | Loop single track or entire playlist |
shuffle | Boolean | Randomize playlist order on track advance |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--audio-player-accent | var(--color-primary) | Play button, slider thumbs, and progress fill color |
--audio-player-bg | var(--color-surface) | Player background and slider thumb border color |
--audio-player-radius | var(--radius-m) | Player border radius |
--audio-player-text | var(--color-text) | Track title and controls text color |
--audio-player-border | var(--color-border) | Player border and slider track color |
--audio-player-shadow | none | Player box shadow (opt-in) |
--audio-player-padding | var(--size-xs) var(--size-s) | Controls area padding |
Dark Mode
The player adapts automatically to light and dark mode via design tokens. All colors resolve through CSS custom properties that respond to theme changes. Wrap any ancestor in data-mode="dark" or let the system preference apply.
Elevated Card Style
Opt in to a shadow with --audio-player-shadow for a raised card look.
Shadow Parts
| Part | Description |
|---|---|
player | Outer player container |
controls | Controls row |
play-button | Play/pause button |
timeline | Seek range input |
volume | Volume range input |
track-info | Track title and time display |
Events
| Event | Detail |
|---|---|
audio-player:play | { currentTime, src } |
audio-player:pause | { currentTime } |
audio-player:ended | { src } |
audio-player:track-change | { src, title } |
Keyboard Shortcuts
| Key | Action |
|---|---|
| Space | Play / Pause |
| Left Arrow | Seek back 10 seconds |
| Right Arrow | Seek forward 10 seconds |
| M | Toggle mute |
Progressive Enhancement
The <audio> element lives in light DOM. Before JS loads, native controls render. After the component upgrades, native controls are hidden and custom chrome takes over. If the component is removed from the DOM, native controls are restored.
Track List Data Attributes
<li> elements in .track-list use data attributes for state:
| Attribute | Set by | Meaning |
|---|---|---|
data-audio-active | Component + author | Currently loaded/playing track |
data-audio-played | Component | Track has been played this session |
data-audio-favorite | Author | Editorially marked as a highlight |
Accessibility
- All controls have
aria-labelattributes - Controls group has
role="group"with label - Keyboard navigable with documented shortcuts
- Respects
prefers-reduced-motion - Falls back to fully accessible native
<audio>without JS
Companion: audio-visualizer
Pair with <audio-visualizer> for canvas-based frequency or waveform display. The visualizer is a separate component — it connects to any <audio> via the for attribute.
Related
<audio>— Native audio element (Layers 1-3)<audio-visualizer>— Canvas visualization companion