Styling < audio > element

How do I change the appearance of the < audio > element?

When I access my web page on in Windows I see this…

image

And when I access the same web page on my Mac I see this…

image

As @coothead and @Ray.H were helping me in another thread, I’m not sure if I messed something up, or if the difference I see are between operating systems?

Not surprisingly, I think the Windows version is large, clunky, and ugly.

Is there a way to make the player look like the second example or style things even more to my liking?

I think you have your images backwards. The square ended player is what I see on windows.

Seeing how your pressed for time it would be best not to worry about it now. Also keep in mind that the users default player is what they are used to seeing anyways.

I suspect the video player is similar to form controls, there will probably be some styles you can’t override or change.

See the <audio> element “Styling with CSS” in the usage notes at MDN.

The <audio> element has no intrinsic visual output of its own unless the controls attribute is specified, in which case the browser’s default controls are shown.

The default controls have a display value of inline by default, and it is often a good idea set the value to block to improve control over positioning and layout, unless you want it to sit within a text block or similar.

You can style the default controls with properties that affect the block as a single unit, so for example you can give it a border and border-radius , padding , margin , etc. You can’t however style the individual components inside the audio player (e.g. change the button size or icons, change the font, etc.), and the controls are different across the different browsers.

To get a consistent look and feel across browsers, you’ll need to create custom controls; these can be marked up and styled in whatever way you want, and then JavaScript can be used along with the HTMLMediaElement API to wire up their functionality.

So it sounds like you can give the main block container round corners with border-radius.

If you want to know what all is involved with the default styles from firefox on windows just take a look at the mozilla videocontrols.css file.

If you use your inspector tool in FF you will see these styles.

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

@namespace url("http://www.w3.org/1999/xhtml");

.videocontrols {
  writing-mode: horizontal-tb;
  width: 100%;
  height: 100%;
  display: inline-block;
  overflow: hidden;

  direction: ltr;
  /* Prevent unwanted style inheritance. See bug 554717. */
  text-align: left;
  list-style-image: none !important;
  font: normal normal normal 100%/normal sans-serif !important;
  text-decoration: none !important;
  white-space: normal !important;
}

.controlsContainer {
  --clickToPlay-size: 48px;
  --button-size: 30px;
  --timer-size: 40px;
  --timer-long-size: 60px;
  --track-size: 5px;
  --thumb-size: 13px;
  --label-font-size: 13px;
  --pip-toggle-bgcolor: rgb(0, 96, 223);
  --pip-toggle-text-and-icon-color: rgb(255, 255, 255);
  --pip-toggle-padding: 5px;
  --pip-toggle-icon-width-height: 16px;
}
.controlsContainer.touch {
  --clickToPlay-size: 64px;
  --button-size: 40px;
  --timer-size: 52px;
  --timer-long-size: 78px;
  --track-size: 7px;
  --thumb-size: 16px;
  --label-font-size: 16px;
}

/* Some CSS custom properties defined here are referenced by videocontrols.js */
.controlBar {
  /* Do not delete: these variables are accessed by JavaScript directly.
     see videocontrols.js and search for |-width|. */
  --clickToPlay-width: var(--clickToPlay-size);
  --playButton-width: var(--button-size);
  --scrubberStack-width: 64px;
  --muteButton-width: var(--button-size);
  --volumeStack-width: 48px;
  --castingButton-width: var(--button-size);
  --closedCaptionButton-width: var(--button-size);
  --fullscreenButton-width: var(--button-size);
  --positionDurationBox-width: var(--timer-size);
  --durationSpan-width: var(--timer-size);
  --positionDurationBox-width-long: var(--timer-long-size);
  --durationSpan-width-long: var(--timer-long-size);
}

.touch .controlBar {
  /* Do not delete: these variables are accessed by JavaScript directly.
     see videocontrols.js and search for |-width|. */
  --scrubberStack-width: 84px;
  --volumeStack-width: 64px;
}

.controlsContainer [hidden],
.controlBar[hidden],
.pictureInPictureToggleButton[hidden],
.videocontrols[inDOMFullscreen] > .controlsContainer > .controlsOverlay > .pictureInPictureToggleButton {
  display: none;
}

.controlBar[size="hidden"] {
  display: none;
}

.controlsSpacer[hideCursor] {
  cursor: none;
}

.controlsContainer,
.progressContainer {
  position: relative;
  height: 100%;
}

.stackItem {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

.statusOverlay {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgb(80,80,80, .85);
}

.controlsOverlay {
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
}

.controlsSpacerStack {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  justify-content: center;
  align-items: center;
}

.controlBar {
  position: relative;
  display: flex;
  box-sizing: border-box;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  height: 40px;
  padding: 0 9px;
  background-color: rgba(26,26,26,.8);
}

.touch .controlBar {
  height: 52px;
}

.controlBar > .button {
  height: 100%;
  min-width: var(--button-size);
  min-height: var(--button-size);
  padding: 6px;
  border: 0;
  margin: 0;
  background-color: transparent;
  background-repeat: no-repeat;
  background-position: center;
  background-origin: content-box;
  background-clip: content-box;
  -moz-context-properties: fill;
  fill: #ffffff;
}

.touch .controlBar > .button {
  background-size: 24px 24px;
}

.controlBar > .button:hover {
  fill: #48a0f7;
}

.controlBar > .button:hover:active {
  fill: #2d89e6;
}

.playButton {
  background-image: url(chrome://global/skin/media/pauseButton.svg);
}
.playButton[paused] {
  background-image: url(chrome://global/skin/media/playButton.svg);
}

.muteButton {
  background-image: url(chrome://global/skin/media/audioUnmutedButton.svg);
}
.muteButton[muted] {
  background-image: url(chrome://global/skin/media/audioMutedButton.svg);
}
.muteButton[noAudio],
.muteButton[noAudio]:hover,
.muteButton[noAudio]:hover:active {
  background-image: url(chrome://global/skin/media/audioNoAudioButton.svg);
  fill: white;
}
.muteButton[noAudio] + .volumeStack {
  display: none;
}

.castingButton {
  background-image: url(chrome://global/skin/media/castingButton-ready.svg);
}

.castingButton[enabled] {
  background-image: url(chrome://global/skin/media/castingButton-active.svg);
}

.closedCaptionButton {
  background-image: url(chrome://global/skin/media/closedCaptionButton-cc-off.svg);
}
.closedCaptionButton[enabled] {
  background-image: url(chrome://global/skin/media/closedCaptionButton-cc-on.svg);
}

.fullscreenButton {
  background-image: url(chrome://global/skin/media/fullscreenEnterButton.svg);
}
.fullscreenButton[fullscreened] {
  background-image: url(chrome://global/skin/media/fullscreenExitButton.svg);
}

.controlBarSpacer {
  flex-grow: 1;
}

.volumeControl::-moz-range-thumb,
.scrubber::-moz-range-thumb {
  height: var(--thumb-size);
  width: var(--thumb-size);
  border: none;
  border-radius: 50%;
  background-color: #ffffff;
  filter: drop-shadow(0px 0px 2px rgba(0,0,0,0.65));
}

.volumeControl::-moz-focus-outer,
.scrubber::-moz-focus-outer {
  border: 0;
}

.progressBackgroundBar {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.progressStack {
  position: relative;
  width: 100%;
  height: var(--track-size);
}

.scrubberStack {
  /* minus margin to get basis of required width */
  min-width: calc(var(--scrubberStack-width) - 18px);
  flex-basis: calc(var(--scrubberStack-width) - 18px);
  flex-grow: 2;
  flex-shrink: 0;
  margin: 0 9px;
}

.volumeStack {
  max-width: 60px;
  min-width: var(--volumeStack-width);
  flex-grow: 1;
  flex-shrink: 0;
  margin-right: 6px;
  margin-left: 4px;
}

.bufferBar,
.progressBar,
.scrubber,
.volumeBackground,
.volumeControl {
  bottom: 0;
  left: 0;
  position: absolute;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: calc(var(--track-size) / 2);
  margin: 0;
  background: none;
  background-color: transparent;
}

.bufferBar,
.volumeBackground {
  background-color: rgba(0,0,0,0.7);
}

.bufferBar::-moz-progress-bar,
.progressBar::-moz-progress-bar,
.volumeBackground::-moz-meter-bar {
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: calc(var(--track-size) / 2);
  background: none;
}

.scrubber:hover::-moz-range-thumb,
.volumeControl:hover::-moz-range-thumb {
  background-color: #48a0f7;
}

.scrubber:active::-moz-range-thumb,
.volumeControl:active::-moz-range-thumb {
  background-color: #2d89e6;
}

.scrubber::-moz-range-track,
.scrubber::-moz-range-progress {
  background-color: transparent;
}

.volumeControl::-moz-range-progress,
.volumeControl::-moz-range-track {
  height: var(--track-size);
  border-radius: calc(var(--track-size) / 2);
}

.volumeControl::-moz-range-progress {
  background-color: #ffffff;
}

.volumeControl::-moz-range-track {
  background-color: rgba(0,0,0,0.7);
}


.bufferBar::-moz-progress-bar {
  background-color: rgba(255,255,255,0.3);
  border-radius: calc(var(--track-size) / 2);
}

.progressBar::-moz-progress-bar {
  background-color: #00b6f0;
}

.textTrackList {
  position: absolute;
  right: 5px;
  bottom: 45px;
  max-width: 80%;
  border: 1px solid #000000;
  border-radius: 2.5px;
  padding: 5px 0;
  vertical-align: middle;
  background-color: #000000;
  opacity: 0.7;
}

.touch .textTrackList {
  bottom: 58px;
}

.textTrackList > .textTrackItem {
  display: block;
  width: 100%;
  height: var(--button-size);
  font-size: var(--label-font-size);
  padding: 2px 10px;
  border: none;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  color: #ffffff;
  background-color: transparent;
}

.textTrackList > .textTrackItem:hover {
  background-color: #444444;
}

.textTrackList > .textTrackItem[on] {
  color: #48a0f7;
}

.positionLabel,
.durationLabel {
  display: none;
}

.positionDurationBox {
  text-align: center;
  padding-inline-start: 1px;
  padding-inline-end: 9px;
  white-space: nowrap;
  font: message-box;
  font-size: var(--label-font-size);
  font-size-adjust: 0.55;
  color: #ffffff;
}


.duration {
  display: inline-block;
  white-space: pre;
  color: #929292;
}

.statusIcon {
  width: 36px;
  height: 36px;
  margin-bottom: 20px;
}

/* Not showing the throbber on mobile because of conflict with m.youtube.com (see bug 1289412) */
.controlsContainer:not(.mobile) .statusIcon[type="throbber"] {
  background: url(chrome://global/skin/media/throbber.png) no-repeat center;
}

.controlsContainer:not(.mobile) .statusIcon[type="throbber"][stalled] {
  background: url(chrome://global/skin/media/stalled.png) no-repeat center;
}

.statusIcon[type="error"],
.statusIcon[type="pictureInPicture"] {
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

.statusIcon[type="error"] {
  min-width: 70px;
  min-height: 60px;
  background-image: url(chrome://global/skin/media/error.png);
}

.statusIcon[type="pictureInPicture"] {
  min-width: 84px;
  min-height: 84px;
  background-image: url(chrome://global/skin/media/pictureinpicture.svg);
  -moz-context-properties: fill, stroke;
  fill: #fff;
  stroke: #fff;
}

.pictureInPictureToggleButton {
  display: flex;
  -moz-appearance: none;
  position: absolute;
  background-color: var(--pip-toggle-bgcolor);
  color: var(--pip-toggle-text-and-icon-color);
  border: 0;
  padding: var(--pip-toggle-padding);
  right: 0;
  top: 50%;
  transform: translateY(-50%) translateX(calc(100% - var(--pip-toggle-icon-width-height) - 2 * var(--pip-toggle-padding)));
  transition: opacity 160ms linear, transform 160ms linear;
  min-width: max-content;
  pointer-events: auto;
  opacity: 0;
}

.pictureInPictureToggleIcon {
  display: inline-block;
  background-image: url(chrome://global/skin/media/pictureinpicture.svg);
  background-position: center left;
  background-repeat: no-repeat;
  -moz-context-properties: fill, stroke;
  fill: var(--pip-toggle-text-and-icon-color);
  stroke: var(--pip-toggle-text-and-icon-color);
  width: var(--pip-toggle-icon-width-height);
  height: var(--pip-toggle-icon-width-height);
  min-width: max-content;
}

.pictureInPictureToggleLabel {
  margin-inline-start: var(--pip-toggle-padding);
}

/**
 * For the Picture-in-Picture toggle, we don't use the built-in :hover
 * pseudoclass because there are many sites where the arrangement of the DOM
 * or the CSS will conspire to prevent :hover from matching on the <video>
 * itself. PictureInPictureToggleChild takes care of punching through those
 * barriers, and manually sets a .hovering class.
 */

.controlsOverlay.hovering > .pictureInPictureToggleButton {
  opacity: 0.8;
}

.controlsOverlay[hidetoggle="true"].hovering > .pictureInPictureToggleButton:not(.hovering) {
  opacity: 0;
}

.controlsOverlay.hovering > .pictureInPictureToggleButton.hovering {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

@supports -moz-bool-pref("media.videocontrols.picture-in-picture.video-toggle.testing") {
  /**
   * To make automated tests faster, we drop the transition duration in
   * testing mode.
   */
  .pictureInPictureToggleButton {
    transition-duration: 10ms;
  }
}

/* Overlay Play button */
.clickToPlay {
  min-width: var(--clickToPlay-size);
  min-height: var(--clickToPlay-size);
  border-radius: 50%;
  background-image: url(chrome://global/skin/media/playButton.svg);
  background-repeat: no-repeat;
  background-position: 54% 50%;
  background-size: 40% 40%;
  background-color: #1a1a1a;
  -moz-context-properties: fill;
  fill: #ffffff;
  opacity: 0.8;
  position: relative;
  top: 20px;
}

.controlsSpacerStack:hover > .clickToPlay,
.clickToPlay:hover {
  opacity: 0.55;
}

.controlsSpacerStack:hover > .clickToPlay[fadeout] {
  opacity: 0;
}

.controlBar[fullscreen-unavailable] .fullscreenButton {
  display: none;
}

.statusOverlay[fadeout],
.statusOverlay[error] + .controlsOverlay > .controlsSpacerStack {
  opacity: 0;
}

.pictureInPictureOverlay {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  opacity: 1;
  background-color: rgb(12, 12, 13);
}

/* Status description formatting */
.statusLabel {
  padding: 0 10px;
  text-align: center;
  font: message-box;
  font-size: 14px;
  color: #ffffff;
}

.statusLabel {
  display: none;
}

[status="errorAborted"]         > [id="errorAborted"],
[status="errorNetwork"]         > [id="errorNetwork"],
[status="errorDecode"]          > [id="errorDecode"],
[status="errorSrcNotSupported"] > [id="errorSrcNotSupported"],
[status="errorNoSource"]        > [id="errorNoSource"],
[status="errorGeneric"]         > [id="errorGeneric"],
[status="pictureInPicture"]     > [id="pictureInPicture"] {
  display: inline;
}

@media (-moz-windows-default-theme: 0) {
  .controlsSpacer,
  .clickToPlay {
    background-color: transparent;
  }
}
1 Like

@Ray.H,

It just occurred to me that the square audio player is a function of Firefox (not Mac per se) and the rounded player is a function of Chrome (and not Windows per se).

Similar to what you said above, I guess the way the audio player looks is a function of the browser and basically out of my control, huh?

Well as I mentioned above you are limited to some styling on the main container, the audio tag.

Now you will see round corners in FF.

Audio Player

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

	<title>Audio Player</title>

<style>
.audioPlayer{
  display: block;
  border-radius: 20px;
  margin:0 auto;
}

</style>
</head>
<body>

<audio class='audioPlayer' autoplay controls loop  title='Song artist/title goes here...'>
  <source src='#' type='audio/mpeg'>
</audio>

</body>
</html>
1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.