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.
answer
- document order decides
- first playable, not best playable
- a hint that avoids a request
- container is not codec
- fallback text is for non-supporting browsers
basics
~20 sThe 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.
solid answer
~50 sOrdering is the whole mechanism: the browser evaluates each `<source>` top to bottom and commits to the first candidate it thinks it can play, so the most-preferred format must come first — a browser that supports both formats takes whichever you listed above the other. The `type` attribute carries the MIME type, optionally with a `codecs` parameter such as `type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'`, which lets the browser rule a candidate out on the spot instead of making a request to find out. Omit it and the browser may have to fetch bytes before rejecting the file. Two traps: a `src` attribute on the `<video>` itself makes the `<source>` children irrelevant, and the markup between `<video>` and `</video>` is legacy fallback for user agents that do not implement the element — it is not shown when every codec fails.
code
html · 7 lines<video controls width="1280" height="720" poster="frame.jpg">
<!-- modern, smaller: offered first -->
<source src="clip.webm" type="video/webm">
<!-- universal floor: only reached if WebM is unsupported -->
<source src="clip.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
<p>Video is not supported here. <a href="clip.mp4">Download the clip</a>.</p>
</video>go deeper
Recall the shape: several <source> children inside <video>, each with src and type, and the browser plays the first one it supports. Know that <source> has no closing tag.
Explain the ordering rule and what type with a codecs parameter saves the browser, and correct the common belief that the fallback content appears when decoding fails.
Show judgment about which encodes are worth producing at all, why a leftover src silently kills the fallback list, and how a player detects exhaustion via error events on each source rather than relying on inner content.
Own the encoding ladder as a system decision: how many formats the pipeline produces, what the compatibility floor is, and when a streaming manifest replaces a static <source> list entirely.
## The selection algorithm, informally ```html <video controls width="1280" height="720" poster="frame.jpg"> <source src="clip.webm" type="video/webm"> <source src="clip.mp4" type="video/mp4"> <p>Your browser does not support the video element. <a href="clip.mp4">Download the clip</a>.</p> </video> ``` The browser takes the `<source>` children in document order. For each one it asks: do I support this type? If the answer is a confident no, it moves on. If it is plausible, it fetches and attempts to use that resource, and — crucially — it does not go looking for a better one afterwards. **First playable wins.** That single fact determines how you order the list: preferred, most efficient format at the top, universal fallback at the bottom. ## What type actually buys you `type` holds the MIME type of the resource, and may carry the `codecs` parameter, which pins the actual encoder profiles inside the container: ```html <source src="clip.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'> ``` This matters because a container is not a codec. `video/mp4` may hold H.264, HEVC or AV1, and a browser that supports the container may not support what is inside it. With the parameter present the browser can reject a candidate immediately, on a string comparison, with zero network traffic. Without `type` at all it may have to open the resource to discover it cannot use it — wasted bytes and a slower start on exactly the devices that can least afford it. Note the quoting: because the codecs value itself contains double quotes, the attribute is written with single quotes around it. ## src on the element beats source children If the `<video>` element carries its own `src`, the resource selection algorithm uses it and the `<source>` children are ignored entirely. This is a real bug in the wild: someone adds a `src` for a quick test, leaves it in, and the carefully curated fallback list becomes dead markup. Use one style or the other, never both. ## What the fallback content is (and is not) The flow content between `<video>` and `</video>` is shown by user agents that **do not implement the element**. A browser that understands `<video>` renders the element and never displays that content, even when every single `<source>` fails to load or decode. So the paragraph reading "your browser cannot play this video" is, in practice, seen by almost nobody — and it is the wrong place to put your handling for a codec failure. What does happen on failure: each `<source>` that cannot be used fires an `error` event at that `<source>` element. That is the hook a player would use to detect exhaustion of the candidate list and show its own message. It is worth still writing useful fallback content — a download link is friendlier than a sentence about browsers — but do not budget for anyone seeing it. ## Ordering strategy in practice Modern codecs are smaller for the same quality but not universally supported; H.264 in MP4 remains the near-universal floor. So the standard shape is newest first, floor last: ```html <video controls width="1280" height="720" poster="frame.jpg"> <source src="clip.webm" type="video/webm"> <source src="clip.mp4" type="video/mp4"> </video> ``` Invert those two lines and every browser that supports both takes the MP4 — the WebM encode you paid to produce is never requested. Reviewers should read `<source>` order as load-bearing, the same way they read any first-match fallback chain. ## Details that trip people up - `<source>` is a void element: no closing tag, no children. - The same mechanism applies to `<audio>`, with types like `audio/ogg` and `audio/mpeg`. - `<source>` elements must come before any `<track>` children and before the fallback content. - Listing four or five formats is usually waste. Two encodes — one modern, one universal — cover the field; every extra encode costs storage and build time for a shrinking slice of users. - A `<source>` with no `type` is legal, just less efficient; it is better than a *wrong* `type`, which will cause the browser to skip a file it could actually have played.
- Why write type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' instead of just type="video/mp4"?Because the container does not tell the browser what is inside it — an MP4 may hold H.264, HEVC or AV1, and support differs per codec. The `codecs` parameter lets the browser rule the candidate in or out without fetching anything. The attribute is written with single quotes because the value itself contains double quotes.
- A video has both a src attribute and two source children. Which resource plays?The one named by `src`. When the media element carries its own `src`, the resource selection algorithm uses it and the `<source>` children are ignored completely. The fallback list becomes dead markup, which is why a leftover debugging `src` is a classic bug. Pick one style: either `src` on the element, or `<source>` children only.
- None of the source files can be decoded. Will the user see the paragraph written between the video tags?No. That content is only rendered by user agents that do not implement `<video>` at all. A modern browser renders the element and leaves it in a failed state instead. Each unusable `<source>` fires an `error` event at that element, which is the signal a custom player would use to show its own message.
saying these in an interview costs you the question
- Believing the browser picks the smallest or best source
- Expecting fallback content when a codec is unsupported
- Listing the universal MP4 first and never serving WebM
- Keeping src on the element alongside source children
- Treating a MIME container name as a codec guarantee