Skip to content

Theming

py-player supports three customization layers that stack on top of each other: theme presets, CSS variable overrides, and CSS Parts.

Theme Presets

Set the theme attribute to apply a color preset:

html
<py-audio src="audio.mp3" theme="dark"></py-audio>
<py-video src="video.mp4" theme="midnight"></py-video>
<py-player src="media.mp3" theme="nord"></py-player>
PresetDescription
autoFollows system prefers-color-scheme (default)
lightWhite background, light tones
darkDark charcoal tones
midnightDeep blue tones
nordNord color palette
sunsetWarm oranges and reds
forestEarthy greens

Accent Color

Override the accent color independently of the theme:

html
<py-audio src="audio.mp3" theme="dark" accent="#e07b39"></py-audio>
<py-audio src="audio.mp3" theme="nord" accent="#ff6b6b"></py-audio>

Any valid CSS color works: hex, rgb(), hsl(), named colors.

CSS Variables

Override individual design tokens from outside the Shadow DOM:

css
py-audio {
  --py-accent: #e07b39;
  --py-bg: #1a1a2e;
  --py-bg-secondary: #16213e;
  --py-text: #eaeaea;
  --py-radius: 16px;
}

All CSS Variables

VariableDefault (light)Description
--py-accent#378ADDAccent/highlight color
--py-bg#ffffffPrimary background
--py-bg-secondary#f5f5f4Secondary background
--py-bg-hover#ede9e0Hover state background
--py-borderrgba(0,0,0,0.08)Border color
--py-text#1a1916Primary text
--py-text-secondary#6b6860Secondary text
--py-text-muted#a8a59eMuted/disabled text
--py-radius10pxBorder radius
--py-font'DM Sans', system-uiFont family

CSS Parts

Style specific internal elements from outside the Shadow DOM using ::part():

css
py-audio::part(root) {
  border: 2px solid hotpink;
  border-radius: 20px;
}

py-audio::part(btn-play) {
  background: linear-gradient(135deg, #ff6b6b, #feca57);
  border-radius: 50%;
}

py-audio::part(progress-fill) {
  background: #e07b39;
}

Available Parts

Shared (audio + video):

PartDescription
rootOuter container
top-barTitle bar
controlsButton group container
btn-playPlay/pause button
btn-prevPrevious button
btn-nextNext button
progressProgress bar track
progress-fillProgress bar filled portion
progress-thumbProgress bar handle
playlistPlaylist container
playlist-itemIndividual track/chapter item
upload-areaFile upload zone
now-playingCurrent track display

Audio-only:

PartDescription
visualizerVisualizer container
viz-barIndividual frequency bar

Video-only:

PartDescription
video-containerVideo element wrapper
video-controlsBottom controls bar
volume-sliderVolume control
fullscreen-btnFullscreen toggle

Combining Layers

Layers stack: preset → CSS variables → CSS Parts.

html
<style>
  #my-player {
    --py-radius: 20px;
    --py-font: 'Georgia', serif;
  }
  #my-player::part(btn-play) {
    width: 48px;
    height: 48px;
    border-radius: 50%;
  }
</style>

<py-audio
  id="my-player"
  src="audio.mp3"
  theme="forest"
  accent="#2d6a4f"
></py-audio>

Layout + Theme Combinations

Layout and theme are independent — any layout works with any theme:

html
<py-audio layout="visualizer" theme="midnight" accent="#ff6b6b"></py-audio>
<py-audio layout="podcast"    theme="nord"></py-audio>
<py-audio layout="compact"    theme="sunset" accent="#c0392b"></py-audio>