skip to content

video and audio Elements

Native media playback with controls, posters, preload hints, and caption tracks. The question that comes up in practice is why autoplay is blocked — it only works muted and inline, because browsers enforce a user-gesture policy.

part ofHTMLoverview, primer and where to startread it →
on this pageshow

questions

5

An HTML `<video autoplay>` silently refuses to start in Chrome and Safari. Explain the browser autoplay policy and which attributes make autoplay actually work.

level: middleimportance: must knowfreq 72%

answer

  1. not a bug, a browser policy
  2. silence is what unlocks it
  3. two attributes, one for iPhone
  4. muted plus playsinline plus autoplay
  5. gesture required for any audible start

basics

~20 s

Browsers block autoplay of audible media until the user has interacted with the page. Adding the muted attribute lets a video autoplay, and playsinline keeps playback inline on iPhone. Playing with sound requires a real user gesture such as a click.

solid answer

~50 s

Every major browser enforces a user-gesture policy: media that would make noise is not allowed to start on its own. So `<video autoplay>` with an audio track is refused, usually with no visible error — the poster just sits there. The supported pattern is `<video autoplay muted playsinline>`: `muted` makes the playback silent, so the policy permits it, and `playsinline` tells iOS Safari to play inside the layout instead of taking over the screen in fullscreen. `loop` is common alongside them for background video. Note that this is about the *audible* state, not the element: an unmuted `<audio autoplay>` is blocked the same way. If you need sound, you must start playback from a user action — a click on your own play button — and if you unmute a muted video later, some browsers will pause it unless a gesture is in hand.

code

html · 7 lines
html
<!-- Allowed: silent, inline, looping background video -->
<video src="hero.mp4" autoplay muted loop playsinline poster="hero.jpg"
       width="1280" height="720"></video>

<!-- Blocked: audible autoplay without a user gesture -->
<video src="hero.mp4" autoplay poster="hero.jpg"
       width="1280" height="720"></video>

go deeper

for a junior

Recall the working combination: autoplay plus muted, and playsinline so iPhones play inline. Say plainly that autoplay with sound is blocked until the user clicks something.

for a middle

Explain the mechanism — the policy targets audible playback, muted satisfies it, and a genuine user gesture is the only other key. Mention that a blocked start is silent, with no visible error.

for a senior

Show you design for refusal: the poster frame is what a share of users will see, unmuting must hang off a real click, and per-site engagement allowances mean you cannot test your way to a guarantee.

for a principal

Own the product call. Decide where autoplay earns its bandwidth and battery cost at all, set the house pattern for muted decorative video versus user-initiated content, and make the silent-failure path a design requirement rather than a bug ticket.

## The rule in one line A browser will not let a page start making noise by itself. Autoplay is permitted only when playback is silent, or when the user has done something that counts as permission. ## Why the policy exists Before the policy, any page could open with a video ad blaring, and the user's only recourse was to hunt for the tab. Browsers responded by making audible playback a privilege: it must be requested by a user gesture (a click, a tap, a key press) or the media must be muted. This is a browser *policy*, not a line in the HTML specification, which is why the exact thresholds differ between engines — but the muted-or-gesture core is universal, so write markup that satisfies it everywhere rather than probing for the current rules. Some engines soften the rule with a per-site allowance: Chrome tracks how much you have historically watched media on a site (its Media Engagement Index) and may permit audible autoplay there, and Safari lets the user grant a per-site "Allow All Auto-Play" permission. You cannot rely on either — the same page will behave differently for a first-time visitor. ## The markup that actually works ```html <video src="loop.mp4" autoplay muted loop playsinline poster="first-frame.jpg" width="1280" height="720"></video> ``` - **`autoplay`** asks the browser to start as soon as enough data is buffered. On its own it is only a request. - **`muted`** is what makes the request grantable. It is a boolean content attribute; it must be present in the markup (or the corresponding property set before playback is attempted), not toggled afterwards. - **`playsinline`** matters on iPhone. Historically iOS Safari forced any `<video>` into the native fullscreen player when it started; `playsinline` requests inline playback. Without it a "background video" hijacks the screen on the exact devices where that is most disruptive. - **`loop`** is unrelated to the policy but almost always wanted for decorative background video. ## What refusal looks like Nothing dramatic happens. The element stays on its `poster` frame, no error is rendered, and nothing appears in the page. If playback is started from script, `play()` returns a promise that rejects with a `NotAllowedError`, which is the only reliable signal that the policy — rather than a network or codec problem — is the cause. That distinction matters when debugging: a codec failure fires `error` events, a policy refusal does not. ## The trap: unmuting later A popular pattern is to autoplay muted and then offer a "sound on" toggle. That is fine *when the toggle is a real click*. What fails is unmuting on a timer, on scroll, or on page load, because the browser still considers the resulting audible playback ungesture-backed and may pause the element outright. Keep the unmute bound to a genuine user action, and make that action a real `<button>` so keyboard users can reach it. ## Audio is not exempt `<audio autoplay>` is subject to the same policy, and `muted` autoplay of an audio element is pointless, so in practice audio always needs a user gesture. There is no `poster` and no `playsinline` on `<audio>` — those are `<video>` attributes. ## Autoplay interacts with the download hints Writing `preload="none"` next to `autoplay` is contradictory: the browser needs the media data to start playing, so the autoplay request wins and the preload hint is effectively ignored. Similarly, `controls` has no bearing on the policy — showing a control bar does not grant permission, and a muted autoplaying background video usually omits `controls` entirely. ## Practical checklist 1. Decorative/background video: `autoplay muted loop playsinline`, plus a `poster` so the first paint is not blank. 2. Content the user came to watch: no `autoplay` at all — show `controls` and let them press play. This also avoids burning mobile data. 3. Any "start with sound" requirement: put it behind a click, and design for the case where the click never comes. 4. Never assume autoplay succeeded. Whatever the page looks like on the frozen poster frame is what a share of your users will see.

  • Your background video autoplays fine on desktop but takes over the whole screen on an iPhone. What is missing?
    The `playsinline` attribute. Without it, iOS Safari has historically promoted a playing `<video>` into its native fullscreen player. Adding `playsinline` alongside `autoplay muted` requests inline playback within your layout. It is a boolean attribute on `<video>` only, and it is harmless on browsers that already play inline, so include it on every autoplaying video.
  • A page autoplays muted video and unmutes it after three seconds. Why is that unreliable?
    The unmute is not backed by a user gesture, so the playback becomes audible without permission and the browser may pause the element or refuse the state change. Only an actual user action — a click or tap on a control you provide — reliably authorises sound. Bind unmuting to a real `<button>` rather than a timer or a scroll handler.
  • Does adding the controls attribute help autoplay succeed?
    No. `controls` only asks the browser to render its native control bar; it grants no autoplay permission. The policy depends on whether playback would be audible and whether a user gesture occurred. A muted video autoplays with or without `controls`, and an unmuted one is blocked either way.

Autoplay permission works like a shop's sound system: you may play something silently on a screen all day, but the moment you want it audible, someone has to walk over and press the button.

saying these in an interview costs you the question

  • Claiming autoplay is broken or a browser bug
  • Thinking preload="auto" grants autoplay permission
  • Believing controls makes autoplay allowed
  • Unmuting on a timer and expecting it to work
  • Forgetting playsinline and shipping fullscreen takeover on iOS

context

open as a page

In HTML, what does the poster attribute on `<video>` do, and what do `preload="none"`, `preload="metadata"` and `preload="auto"` tell the browser?

level: juniorimportance: should knowfreq 52%

basics

~20 s

poster names an image the browser shows in the video's frame until playback produces a picture. preload is a hint about how much of the media file to fetch before play: none fetches nothing, metadata fetches just duration and dimensions, auto invites the browser to buffer the whole thing.

open as a page

An HTML `<video>` has three `<source>` children in different formats. Explain how the browser picks one, what the `type` attribute contributes, and when the content between the `<video>` tags is displayed.

level: middleimportance: should knowfreq 46%

basics

~20 s

The browser walks the source children in document order and plays the first one it believes it can decode — first playable wins, not best. The type attribute lets it skip unsupported candidates without fetching them. Content between the video tags is fallback only for browsers with no video support at all.

open as a page

How do you add captions to an HTML `<video>` using the `<track>` element, and what distinguishes `kind="captions"` from `kind="subtitles"`?

level: middleimportance: should knowfreq 44%

basics

~20 s

Add a void track child to the video pointing at a WebVTT file, with kind, src, srclang, label and optionally default. Captions convey non-speech audio too and assume the viewer cannot hear; subtitles are a transcription or translation for someone who can hear the audio.

open as a page

A team drops the `controls` attribute from `<video>` and builds their own control bar. What does the native control bar provide that the custom one now has to reproduce?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The native bar is a fully keyboard-operable, screen-reader-labelled, localised player with play, seek, volume, fullscreen, picture-in-picture, a captions menu and OS media-key integration. Removing it hands all of that to the team, and most custom bars rebuild only the visible parts.

open as a page