Newsletter

Hear about new files and fixes

I send an email when I publish something new or release a fix for a file you might already use. There’s no fixed schedule.

Every email has a one-click unsubscribe link, and none of them contain tracking pixels.

Etch component

Audio Player

A clean audio player for podcasts, narrated articles, lessons and sample previews. Choose an MP3 or WAV from the Media Library, pick Compact or Card and a Light, Dark or Inherit theme. Works with the keyboard and screen readers, fits down to 320 px, and offers an optional download, a remembered position and English or Polish controls. Everything is set in the Etch props panel.

Download .jsonSee the demo

Paste it on the Etch canvas with Ctrl+V or ⌘V, then click Save.

Stay up to date. Etch won’t update a pasted component for you. Subscribe and get one email when a new version is out.

Free on unlimited personal, client and commercial sites. Modify it however you like.License: FSL-1.1-MIT
Version
1.0.0-beta.2Changelog
Options
17 settings+ 51 CSS variablesSee all
Tested on Etch
1.7.1
Tested on WordPress
7.1.3
Live demo

12 players in real layouts

Press Play, use Tab and the arrow keys, or pause the podcast, reload and play again. Switch to Mobile to see the controls stack at phone width.

Live
  • Players: 12
  • Layouts: Compact, Card
  • Themes: 3
  • Languages: 2
Open in a new tab
Features

What it does

One pasted component and no setup. The controls are Media Chrome by Mux, bundled into the component, so there is no plugin, no CDN and no extra request.

  • Every control you expect

    Play, back and forward 10 seconds, a timeline with the time, mute, volume and speed from 0.5× to 2×, plus an optional download link. Starting one player pauses the others.

  • Two layouts, three themes

    Compact fits one row in a wide column and stacks in a narrow one; Card adds square artwork. Inherit follows the section around it, Light and Dark draw a finished card from your ACSS colors.

  • Accessible by default

    Eight Tab stops per player, named controls, arrow keys on the timeline and volume, a visible focus ring and 44 px targets. Checked with VoiceOver in Safari.

  • Loads only what it needs

    When Visible waits until the player nears the screen, On Interaction loads nothing until Play, and Eager reads the length with the page. No autoplay, ever.

  • Remembers where you stopped

    Optional Remember Position keeps the spot in the browser for 30 days. System Media Controls show the title and artwork in the system media panel, where the browser supports it.

  • English and Polish

    Controls, tooltips, slider values and messages follow the page language, or you pin one player to English or Polski. Titles stay exactly as you type them.

  • 51 styling variables

    Colors, sizes, corners, the track, the focus ring and tooltips, set on any parent class. ACSS 4 tokens with plain fallbacks, so it works without Automatic.css too.

  • Live in the builder

    The canvas runs the real player, so every prop edit shows at once, without saving. Press Play right in the canvas to hear the file you picked.

Install

Add it in four steps

No plugin and no build step. The component brings its own CSS and two scripts, the player and the bundled Media Chrome controls, so nothing loads from a CDN. It works with or without Automatic.css 4.

Shows without its styles? It was pasted but not saved, and pasting again won’t repair it. Delete ED Audio Player from your components, paste it again and click Save.

  1. Copy the componentUse Copy component at the top of this page, or download the .json file.
  2. Paste it on the Etch canvasSelect where it should go, press Ctrl+V or ⌘V, then click Save. Etch adds the component to your list right away but stores its CSS only when you save.
  3. Choose an audio fileIn Audio File, pick an MP3 or WAV from the Media Library or paste a direct link, then add a Title. The field’s placeholder says Image URL, but the picker accepts audio.
  4. Save and open the pageThe canvas runs the real player, so every setting you change shows at once. On the page, visitors press Play or use the keyboard.
Options

17 settings in the Etch props panel

In the order of the Etch props panel, where each setting has help text too. Only Audio File is needed; without it, a new player shows a short setup prompt.

Name every player

Screen readers announce each player as a region named after its Title, then its Artist. When a page has several players without either, give each one its own Accessible Label, such as Preview: Funk Bass Loops.

Audio File takes a Media Library item or a direct http(s) link. Media files don’t travel with the component, so choose them again on every site.

Audio and text

Audio FileRequiredaudio
An MP3 or WAV from the Media Library, or a direct http(s) link to an audio file. Until you choose one, the player shows a setup prompt.Empty by default.
Titletitle
Visible title, such as Episode 12: Interview. It also names the player for screen readers. Leave it empty to hide it.Empty by default.
Artist / Authorartist
Artist, host or author shown under the title. Names the player when Title is empty.Empty by default.
Accessible LabelaccessibleLabel
Screen-reader name of the player, in your site’s language. Empty uses Title, then Artist, then “Audio player”. Give players without a title distinct labels.Empty by default.

Look

Layoutlayout
Compact: one row of controls in a container 720 px or wider, two rows from 480 px, three below that. Card: 96 px artwork and a larger title above centered controls.Default: Compact
Themetheme
Inherit takes the surrounding text color and font and adapts to dark sections. Light and Dark draw a complete card from your ACSS colors.Default: Inherit
Show ArtworkshowArtwork
Shows the Artwork image beside the title. It is decorative, so screen readers skip it.Default: Off
Artworkartwork
Image from the Media Library, cropped to a square: 64 px in Compact, 96 px in Card. Used only when Show Artwork is on.Empty by default.

Playback

Looploop
Starts again from the beginning when the audio ends.Default: Off
Show DownloadshowDownload
Adds a download link to the file. Browsers may open a file from another domain instead of saving it.Default: Off
Download LabeldownloadLabel
Text of the download link. Leave it empty or at Download and it follows the player’s language, such as Pobierz in Polish.Default: Download
Load MedialoadMedia
When Visible loads the file once the player is within 200 px of the screen. Eager loads its details with the page. On Interaction loads nothing until Play, best for pages with many players.Default: When Visible
Auto Pause Other PlayersautoPauseOtherPlayers
Starting this player pauses the other ED Audio and Video Players on the page. Off: it doesn’t pause others, but they can still pause it.Default: On

Language

Languagelanguage
Language of the controls, tooltips, slider values and messages. Automatic follows the nearest lang attribute or the page language; anything other than Polish uses English.Default: Automatic

Browser features

Remember PositionresumePlayback
Saves the listening position in this browser for 30 days. On the next visit, Play continues from there; playback never starts by itself. Needs a Recording ID.Default: Off
Recording IDresumeKey
A stable, unique ID for this recording, such as podcast-episode-14, up to 128 characters. Empty turns the storage off. Reuse an ID only for the same recording.Empty by default.
System Media ControlsmediaSession
The player that played last shares its title, artist and artwork with the media panel of the phone or computer, with play, pause and seeking. Browser support varies.Default: Off
Styling: 51 CSS variables

Set them on any parent element or class, such as a podcast section. They all inherit, so no extra selectors or !important are needed. The same list sits commented out at the top of the component’s CSS in Etch, but a parent class is safer: it survives updates. “Per Theme” means Inherit, Light and Dark use different values; a value you set wins over all three.

Container

--ed-audio-player-surface
Player background. Inherit: a 5% tint of the text color. Light: --bg-ultra-light. Dark: --bg-dark.Default: per Theme
--ed-audio-player-color
Text and icon color. Inherit keeps the surrounding color; Light uses --text-dark, Dark --text-light.Default: per Theme
--ed-audio-player-muted-color
Artist, time and status text. Inherit keeps the full text color, because page text may already be muted; Light uses --text-dark-muted, Dark --text-light-muted.Default: per Theme
--ed-audio-player-border
Border shorthand, such as 0 for none. Its color comes from the border color variable.Default: 1px solid
--ed-audio-player-border-color
Border color: the text color at 14%, or at 12% in Light.Default: per Theme
--ed-audio-player-radius
Corner radius of the player; the artwork corners follow it.Default: var(--radius, 0.75rem)
--ed-audio-player-shadow
Box shadow. Light and Dark use --box-shadow-1; Inherit has none.Default: per Theme
--ed-audio-player-padding
Inner spacing. Card uses var(--space-m, 1.5rem).Default: var(--space-s, 1rem)
--ed-audio-player-gap
Space between artwork and text, header and controls, and the control rows, which use 4px in Compact and 8px in Card. One value overrides all of these gaps.Default: var(--space-xs, 0.75rem)
--ed-audio-player-max-width
Maximum width, such as 40rem.Default: 100%
--ed-audio-player-font-family
Font of the whole player, including the time, speed and tooltips.Default: inherit
--ed-audio-player-text-size
Base text size.Default: var(--text-m, 1rem)
--ed-audio-player-line-height
Line height.Default: 1.4

Title, artist and artwork

--ed-audio-player-title-color
Title color.Default: inherit
--ed-audio-player-title-font-family
Title font, such as var(--heading-font-family).Default: inherit
--ed-audio-player-title-size
Title size. Card uses var(--text-l, 1.25rem).Default: 1em
--ed-audio-player-title-weight
Title weight.Default: var(--heading-font-weight, 600)
--ed-audio-player-artist-color
Artist color; follows the muted color.Default: var(--ed-audio-player-muted-color)
--ed-audio-player-artist-size
Artist text size.Default: var(--text-s, 0.875rem)
--ed-audio-player-artwork-size
Artwork width and height. Card uses 96px.Default: 64px
--ed-audio-player-artwork-radius
Artwork corners.Default: calc(var(--ed-audio-player-radius) * 0.75)

Play button and accent

--ed-audio-player-accent
Play button, progress and thumb. Dark, and Inherit on a dark section, use var(--primary-light, #9ab6f5).Default: var(--primary, #2456a6)
--ed-audio-player-accent-hover
Play button on hover. The dark variants use --primary-ultra-light.Default: var(--primary-hover)
--ed-audio-player-accent-contrast
Play and pause icon on the accent. The dark variants use --primary-ultra-dark.Default: var(--white, #fff)
--ed-audio-player-play-size
Play button size. Card uses 56px.Default: 48px
--ed-audio-player-play-radius
Play button corners, such as var(--radius) for a rounded square.Default: 999px
--ed-audio-player-play-icon-size
Play and pause icon size.Default: 24px

Other controls

--ed-audio-player-control-color
Seek, mute, speed and download color.Default: inherit
--ed-audio-player-control-hover-background
Hover background of those controls.Default: color-mix(in oklch, currentColor 12%, transparent)
--ed-audio-player-chip-background
Resting background of the speed and download chips, and of an empty artwork square.Default: color-mix(in oklch, currentColor 7%, transparent)
--ed-audio-player-control-size
Height of the buttons and the download link. Keep 44px or more for touch.Default: 44px
--ed-audio-player-control-radius
Corners of buttons, chips and the slider focus ring.Default: 999px
--ed-audio-player-control-gap
Space between controls in a group: 8px around the timeline and 12px in the Card transport by default. One value overrides all of them.Default: 4px
--ed-audio-player-icon-size
Seek and mute icon size.Default: 24px

Timeline, volume and time

--ed-audio-player-track-color
Timeline and volume track.Default: color-mix(in oklch, currentColor 18%, transparent)
--ed-audio-player-buffered-color
Loaded part of the timeline, drawn over the track.Default: color-mix(in oklch, currentColor 16%, transparent)
--ed-audio-player-progress-color
Played part and volume level; follows the accent.Default: var(--ed-audio-player-accent)
--ed-audio-player-thumb-color
Timeline and volume thumb; follows the progress color.Default: var(--ed-audio-player-progress-color)
--ed-audio-player-track-height
Track thickness.Default: 6px
--ed-audio-player-track-radius
Track corners.Default: 999px
--ed-audio-player-thumb-size
Thumb diameter.Default: 14px
--ed-audio-player-volume-width
Volume slider width.Default: 88px
--ed-audio-player-time-color
Current time and length; follows the muted color.Default: var(--ed-audio-player-muted-color)
--ed-audio-player-time-size
Time text size.Default: var(--text-s, 0.875rem)

Focus, tooltips, errors and motion

--ed-audio-player-focus-color
Keyboard focus ring. Light and Inherit use --focus-color; Dark uses --primary-light, and Inherit on a dark section the text color.Default: per Theme
--ed-audio-player-focus-width
Focus ring width.Default: 2px
--ed-audio-player-focus-offset
Gap between a control and its focus ring.Default: 2px
--ed-audio-player-tooltip-background
Tooltip background: --text-dark, or --text-light in the dark variants.Default: per Theme
--ed-audio-player-tooltip-color
Tooltip text: white, or --text-dark in the dark variants.Default: per Theme
--ed-audio-player-error-color
Color of the “Unable to load this audio” message. The dark variants use #ffb4ab.Default: #b3261e
--ed-audio-player-transition
Hover and press transitions; reduced motion turns them off.Default: var(--transition, 0.2s ease)
License

Free to use. Not for resale.

Licensed under FSL-1.1-MIT, the Functional Source License with an MIT future license. Each version becomes MIT-licensed two years after its release.

You can
  • Use it on unlimited personal, client and commercial websites
  • Modify and adapt it however you like
  • Use it in paid design and development work for your clients
You can’t
  • Sell it, or a modified version, as a component: in a library, bundle, template kit, plugin or marketplace listing
  • Offer it in another commercial product or service that competes with it

Keep the copyright and license notices in the code, and link to this page instead of re-hosting the download, so everyone gets fixes and updates. Read the full license

Third-party code

This component bundles the open-source library below, unchanged. It keeps its own license, and FSL-1.1-MIT does not apply to it. Its full notice opens the component’s controls script and the CSS names it; keep both when you use or change the component.

Updates

How to update

Etch has no update button for pasted components. Pasting a newer version over an installed one changes nothing: Etch keeps the component and the CSS it already has. To update, reinstall in five steps.

  1. Note what you setWrite down the settings of each player, including its audio file, artwork and Recording ID, and copy any CSS you changed in the component’s own styles.
  2. Delete the componentIn Etch, delete ED Audio Player from your components. Every player disappears from every page that used it.
  3. Delete its stylesIn the Style Manager, search for ed-audio-player and delete the 24 styles listed below. Only the first one holds CSS; the others are empty class names.
  4. Paste the new versionCopy or download the new JSON from this page, paste it on the canvas and click Save. Etch creates the component and its CSS fresh.
  5. Put your players backInsert a player wherever one was, choose its audio file, re-enter its settings and save. Reload any other open builder tab.

Styles to delete in step 3

  • .ed-audio-player
  • .ed-audio-player__header
  • .ed-audio-player__artwork
  • .ed-audio-player__image
  • .ed-audio-player__meta
  • .ed-audio-player__title
  • .ed-audio-player__artist
  • .ed-audio-player__controller
  • .ed-audio-player__media
  • .ed-audio-player__controls
  • .ed-audio-player__transport
  • .ed-audio-player__back
  • .ed-audio-player__play
  • .ed-audio-player__forward
  • .ed-audio-player__progress
  • .ed-audio-player__timeline
  • .ed-audio-player__time
  • .ed-audio-player__utilities
  • .ed-audio-player__mute
  • .ed-audio-player__volume
  • .ed-audio-player__rate
  • .ed-audio-player__download
  • .ed-audio-player__status
  • .ed-audio-player__fallback

Trade-offs

  • Placements are not kept. Etch doesn’t link old players to the new component, so you insert each one again and re-enter its settings.
  • Edits inside the component’s CSS are replaced. Keep overrides on a parent class with the --ed-audio-player-* variables; those survive an update.
  • Skipping a step leaves a mix. Without step 2, Etch keeps the old component. Without step 3, the new version runs on the old CSS.
  • Saved positions carry over. Remember Position keys each position by Recording ID and audio file, so reuse both and listeners keep their place.

Coming from 1.0.0-beta.1? Follow the five steps above. Settings, classes and styling variables are unchanged, so you can re-enter your settings as they were. Subscribe and you’ll get one email when the next version is out.

Changelog

What changed

Versions follow semantic versioning. When an update changes how existing options behave, its entry says so.

1.0.0-beta.2Latest
  • FixedWith TalkBack, swiping up or down on the timeline or the volume jumped to the start or the end; with VoiceOver the sliders didn’t move. One swipe now moves either slider by 5%, and the arrow keys keep their steps.
  • FixedWith TalkBack resting on the timeline, the position was read out every second while the audio played. The timeline now stays quiet during playback; the visible time keeps running.
  • FixedOn phones and tablets, a vertical swipe that starts on the timeline or the volume slider now scrolls the page instead of seeking or changing the volume. A tap still sets the value, and a sideways drag scrubs.
  • ChangedOn iPhone the volume slider is hidden, because iOS sets the volume only with the hardware buttons. Mute stays, and iPad and desktop keep the slider.
  • FixedA wide Compact player could load in the narrow three-row layout (seen in Microsoft Edge). In Safari, a paused timeline now shows exactly where playback stopped.
  • ChangedThe player script and the CSS of .ed-audio-player changed, so update the component and its styles together (see How to update). Props, classes, styling variables and the bundled Media Chrome 4.19.2 are the same.
  • TestedTalkBack on Android, Safari on iPhone and iPad in the iOS Simulator, and Chrome, Firefox, Microsoft Edge and WebKit on the desktop. It stays a beta until NVDA and VoiceOver on a real iPhone are tested.
1.0.0-beta.1
  • ReleasedFirst public version. It stays a beta until NVDA, VoiceOver on iOS, TalkBack, Microsoft Edge and touch devices are tested.
Feedback

Tell me what this component needs

A bug, a missing option, or anything that made the component awkward to use in a real build — it all belongs here. The versions above are the ones it was tested on; if yours differ, say so.