HTML Video Element Table

AttributeWhat it doesField note
controlsNative playback UIThe accessible player for free - build custom only with real reasons
autoplay + muted + playsinlineThe silent-autoplay trioALL THREE together = autoplay allowed - unmuted never autoplays
posterPre-play frameSaves the first-frame download as your LCP image
preload="metadata"Fetch header info onlynone = nothing; auto = maybe everything - metadata is the polite default
<source> elementsFormat fallbacksBrowser takes the FIRST it can play - list AV1, then WebM, then MP4
width/heightRatio reservationSame CLS math as img - reserve before the bytes arrive
muted / volumeAudio controlmuted reflects the attribute; volume is JS-only (0-1 property)
loop / playbackRateLoop and speedplaybackRate via JS - the player feature set is scriptable
Reference: the MDN video element reference. The video element's central law is the AUTOPLAY POLICY: browsers allow autoplay only for SILENT video - which is why the working incantation is the trio autoplay muted playsinline (without playsinline, iOS fullscreen-hijacks; without muted, blocked). Bottom line: source elements give format fallbacks without JavaScript (the browser picks the first codec it can play), poster saves your hero frame from a first-frame download, preload=metadata is the polite default, and width/height reserve the ratio against layout shift - the same contract as images. Related tools: img table (the shared CLS contract), getUserMedia table (video that RECORDS instead of plays), and backgrounds table (when a looping background video beats a gif).

The video element's central law is the AUTOPLAY POLICY: browsers allow autoplay only for SILENT video, which is why the working incantation is the trio autoplay + muted + playsinline - drop muted and the browser blocks it, drop playsinline and iOS hijacks the screen with a fullscreen takeover.

Bottom line: source elements give format fallbacks without JavaScript - the browser takes the FIRST it can play, so list modern codecs (AV1, WebM) before the universal MP4. poster supplies the pre-play frame (saving your hero from a first-frame download), and preload=metadata is the polite default between 'nothing' and 'maybe everything'.

The honest part: the native controls are the accessible player for free - keyboard operable, screen-reader labeled, captions-wired. Build a custom player only with real design reasons, and then YOU own the keyboard map, the focus states and the caption toggle that controls shipped yesterday.

How to use

  1. Ship the autoplay hero: <video autoplay muted playsinline loop> with a poster - background video that starts everywhere, no sound by contract.
  2. List sources old-new: <source src=a.av1 type=video/av1><source src=a.webm type=video/webm><source src=a.mp4 type=video/mp4> - first playable wins, no JavaScript.
  3. Reserve the box: width and height attributes on video, same as img - the aspect-ratio box kills layout shift before the metadata arrives.

Frequently asked questions

Why does autoplay work on my machine but not for users?

The autoplay policy evaluates per context, not per attribute. Muted videos autoplay essentially everywhere; UNMUTED autoplay requires engagement signals (the user has played media on your site before, or has site-specific settings) - so your dev profile, full of history, plays and their fresh browser does not. iOS adds the playsinline requirement: without it, autoplaying video takes over the fullscreen video controller. The robust pattern never relies on unmuted autoplay: start muted with a visible unmute button, or gate playback behind a play click. detect autoplay (video.play() promise rejection) if the behavior matters.

What does preload actually control, and which value should I ship?

A hint with three levels: none downloads nothing until play (minimal cost, slow start), metadata fetches duration and dimensions only (enables ratio reservation and player UI), auto lets the browser download as it pleases (fast start, potentially heavy). The default is browser-defined 'auto-ish', which is why background pages with many videos can silently download megabytes. Ship metadata for player-attached videos (the polite default that still knows the dimensions), none for below-the-fold or click-to-play, and reserve space with dimensions regardless - the hint can be ignored by the browser, the attributes cannot.

How do source fallbacks actually get chosen?

Top-down first-match. The browser evaluates source elements in order and takes the FIRST whose type attribute it can decode - type is what lets it decide WITHOUT downloading (if you omit type, it must fetch and sniff, wasting requests). The ordering strategy is therefore newest-and-best first: AV1 or WebM (smaller at equal quality) before the universal MP4/H.264 fallback that every device including old ones decodes. The video element itself is the fallback of last resort - its inner content renders in engines that do not know video at all, which is where a download link or poster message lives.

When is a video element the wrong tool versus CSS animation or GIF?

For short decorative loops, a muted autoplaying video is actually the RIGHT tool - it is smaller than GIF (real codecs beat GIF's 256-color palette by an order of magnitude) and smoother. Video becomes wrong when: the visual is simple enough for CSS (a gradient pulse costs zero bytes and never buffers), when audio must sync precisely (Web Audio's domain), or when the 'video' is interactive (that is canvas or a real player). The GIF comparison deserves emphasis: converting a GIF to a muted looped MP4 or WebM typically cuts size 90%+ - the animated GIF survives on the web only as a format for chat apps, not for pages.

Related tools