HTML Audio
The <audio> element lets you embed sound directly in a web page — music, podcasts, sound effects, voice recordings — without relying on a plugin like Flash. The browser provides its own built-in player interface (or you can control playback with JavaScript), so you can drop in a working audio player with a single tag. Because not every browser supports every audio codec, the element also has a built-in fallback mechanism so you can offer multiple file formats and a text alternative for browsers that can’t play any of them.
Overview / How it works
The <audio> element is one of HTML5’s media elements, alongside <video>. In the DOM, it becomes an HTMLAudioElement node — a replaced element, meaning the browser substitutes its own rendering (a native player widget) for the element’s content, rather than laying out the element the way it lays out ordinary text or block content. If you don’t add the controls attribute and the audio isn’t set to autoplay, the element takes up no visible space at all — it plays sound with no visual trace, which is why forgetting controls is one of the most common beginner mistakes.
Unlike an <img>, which has one src, audio files come in competing formats (MP3, OGG/Vorbis, WAV, and others) and no single format is guaranteed to be decodable by every browser and device. To solve this, <audio> supports one or more child <source> elements, each pointing to a different encoded file. The browser walks through them in order and plays the first one it can actually decode, ignoring the rest. This is the same fallback pattern used by <picture> for images.
Semantically, <audio> tells the browser and assistive technology “this is an embedded sound clip with a player” — it carries no information about what the sound actually contains. Because screen readers and search engines cannot “listen” to the file, any spoken content (a podcast, an interview, narration) should have a text transcript or captions available elsewhere on the page. The <audio> element itself has no visual styling hooks for its native controls; the play button, seek bar, and volume slider are drawn by the browser’s own UI, not by your CSS. If you need a fully custom-looking player, you build it with the JavaScript media API and hide the native controls — that’s beyond the scope of this HTML lesson.
Syntax
<audio src="file.mp3" controls autoplay loop muted preload="metadata">
Fallback text or a download link for unsupported browsers.
</audio>
Attributes you’ll use most often:
| Attribute | Purpose |
|---|---|
src |
URL of the audio file. Optional on the <audio> tag itself if you instead provide one or more <source> children. |
controls |
Boolean attribute. Tells the browser to display its native play/pause, seek bar, volume, and time UI. Without it, there is no visible player. |
autoplay |
Boolean attribute. Asks the browser to start playback as soon as enough data is available. Most browsers refuse to autoplay audible sound without a prior user interaction — it generally only works combined with muted. |
loop |
Boolean attribute. Restarts playback from the beginning automatically when the file ends. |
muted |
Boolean attribute. The player starts with volume muted; the user can unmute via the controls. |
preload |
Hint for how much to load before playback is requested: none, metadata (just duration/dimensions), or auto (as much as the browser thinks useful). |
crossorigin |
Set to anonymous or use-credentials when the audio needs to be read cross-origin (for example, by a JavaScript audio-analysis API). |
Inside <audio> you can place one or more <source src="..." type="..."> elements (each self-closing/void, with no closing tag) instead of a single src attribute, plus any fallback content — text, a link, even a paragraph — that only renders in browsers unable to play any of the supplied sources.
Examples
Example 1: A basic audio player
<audio src="ocean-waves.mp3" controls>
Your browser does not support the audio element.
</audio>
Result: The browser renders its native audio player widget inline: a play/pause button, a scrubbable progress bar showing elapsed and total time, and a volume control. The fallback sentence never appears in any modern browser because they all support <audio>; it would only show up in an extremely old or non-graphical browser.
This is the minimal usable pattern: one file, controls so the user can actually interact with it, and a short text fallback as a safety net.
Example 2: Multiple formats with a download fallback
<audio controls preload="metadata">
<source src="podcast-episode.mp3" type="audio/mpeg">
<source src="podcast-episode.ogg" type="audio/ogg">
<source src="podcast-episode.wav" type="audio/wav">
<p>
Your browser doesn't support HTML audio.
<a href="podcast-episode.mp3">Download the podcast episode</a> instead.
</p>
</audio>
Result: The browser tests the <source> elements from top to bottom, checking each type against the codecs it supports, and plays the first one it can decode — typically the MP3 in most modern browsers. Because preload="metadata" is set, the player shows the correct total duration immediately without downloading the whole file. If, hypothetically, none of the three formats were supported, the fallback paragraph with the download link would render instead of a player.
This is the pattern to use whenever you need broad compatibility: list your most broadly-supported format first, add alternates after it, and always give the type attribute so the browser can skip files it can’t play without wasting a download.
Example 3: Looping, muted ambient background audio
<figure>
<audio controls autoplay muted loop preload="auto">
<source src="rain-ambience.mp3" type="audio/mpeg">
<source src="rain-ambience.ogg" type="audio/ogg">
</audio>
<figcaption>Looping rain ambience (starts muted — use the player's volume control to unmute).</figcaption>
</figure>
Result: As soon as the page loads, the browser begins playing the rain-ambience file automatically, but silently, because pairing autoplay with muted is the one combination browsers reliably allow without a prior click. When the clip reaches its end, loop makes it restart immediately and seamlessly. The controls attribute still displays the native player, so a visitor can unmute, pause, or scrub through it, and the <figcaption> displays a caption underneath describing what the sound is and how to control it.
Wrapping the player in <figure>/<figcaption> gives the audio a semantic, machine-readable caption — the same pattern used for captioned images.
How it works step by step / Under the hood
- The HTML parser reaches the
<audio>start tag and constructs anHTMLAudioElementnode in the DOM tree, just like any other element. - The browser runs its “resource selection” algorithm: if the
<audio>tag itself has asrcattribute, that URL is used directly. Otherwise, the browser walks the child<source>elements in document order. - For each
<source>, the browser checks thetypeattribute against the codecs it knows how to decode (via an internal check equivalent to the JavaScriptcanPlayType()method). Iftypeis a supported MIME type, that source is chosen immediately without downloading the file first; iftypeis omitted, the browser has to fetch some of the file and inspect it directly, which is slower. - Once a playable source is selected, the browser begins fetching it according to the
preloadhint and prepares to decode audio data as it arrives. - If
controlsis present, the browser renders its native player chrome inside the element’s box. This chrome lives in the browser’s own internal rendering (often described as UI outside normal CSS reach) — you cannot restyle the scrub bar or buttons with ordinary CSS selectors. - If
autoplayis set, the browser attempts to start playback once enough data has buffered, but the browser’s autoplay policy will block it if the audio would be audible and the user hasn’t previously interacted with the page or site —mutedis the standard workaround. - If
loopis set, when the media’s internal “ended” state is reached, the browser seeks back to the start and resumes playback rather than stopping. - If none of the sources can be decoded (or there is no supported
src/sourceat all), the browser renders whatever fallback content is inside the<audio></audio>tags — text, links, images — exactly as if the audio element weren’t there.
Common Mistakes
Mistake 1: Forgetting the controls attribute
<audio src="song.mp3"></audio>
Without controls and without autoplay, this element is completely invisible and does nothing — no player appears, and nothing plays. Beginners often assume the tag alone produces a visible widget.
Corrected:
<audio src="song.mp3" controls></audio>
Mistake 2: Expecting unmuted autoplay to work
<audio src="song.mp3" autoplay controls></audio>
Modern browsers block audible autoplay to stop sites from blasting sound at visitors without consent. This will often simply fail to play until the user clicks the button themselves, which looks like a bug rather than intended behavior.
Corrected (mute it, or drop autoplay and let the user press play):
<audio src="song.mp3" autoplay muted controls></audio>
Mistake 3: Putting two src attributes on one tag instead of using <source>
<audio src="song.mp3" src="song.ogg" controls></audio>
An element can only carry one instance of a given attribute; a duplicate src is invalid markup and any validator will flag it, and browsers simply keep the first (or last) one and silently drop the other, defeating the intent of offering a fallback format.
Corrected — use one <source> child per format:
<audio controls>
<source src="song.mp3" type="audio/mpeg">
<source src="song.ogg" type="audio/ogg">
</audio>
Best Practices
- Always include
controlsunless you are deliberately building silent, muted background audio — users should be able to pause or adjust volume themselves. - Offer at least two encoded formats (commonly MP3 plus OGG) via
<source>elements, since no single audio codec is supported everywhere. - Always add a
typeattribute to each<source>so the browser can skip formats it can’t decode without downloading them first. - Never rely on unmuted
autoplay; treat it as something browsers will block by default. - Provide a text transcript or written summary near spoken audio (podcasts, interviews, narration) for accessibility and so search engines can index the content.
- Use
preload="none"on pages with many audio elements to avoid wasting bandwidth on files nobody plays, orpreload="metadata"to show duration without buffering the whole file. - Always include meaningful fallback content between the tags for the rare browser or crawler that can’t process the element.
- Avoid using looping background audio without an obvious, easy way for the visitor to mute or stop it — it can be jarring or genuinely inaccessible for some users.
Practice Exercises
- Embed a local file named
welcome.mp3with visible controls and appropriate fallback text inside the tags. Open the page in a browser and confirm the player appears and works. - Starting from
<audio controls></audio>, add two<source>children pointing attrack.mp3andtrack.oggwith correcttypeattributes, plus a fallback paragraph containing a direct download link. - Build a looping ambient sound player (for example,
cafe-noise.mp3) that starts muted and autoplays, wrapped in a<figure>with a<figcaption>explaining that it starts muted. Verify in your browser that it plays silently on load and that unmuting it via the native controls works.
Summary
- The
<audio>element embeds a native sound player using either asrcattribute or one or more<source>children for format fallback. - Without
controls(orautoplay), the element renders no visible player at all. - Multiple
<source>elements withtypeattributes let the browser pick the first format it can decode, without downloading formats it can’t play. - Browsers block unmuted autoplay by default; pair
autoplaywithmutedif you need automatic playback. - The native player controls are browser-rendered UI, not something you can restyle with normal CSS.
- Always provide a text fallback or transcript, since audio content isn’t readable by search engines or screen readers.
