Media Elements
HTML5 Media Overview
Modern HTML provides native elements for audio, video, and embedded content — no Flash required. Understanding these elements is essential for accessible, performant multimedia pages.
| Element | Purpose |
|---|---|
<video> |
Video playback with controls |
<audio> |
Audio playback |
<picture> |
Responsive images with format fallbacks |
<source> |
Multiple media sources for <video>, <audio>, <picture> |
<track> |
Captions, subtitles, chapters for video |
<iframe> |
Embed external documents (YouTube, maps, widgets) |
Video Element
<video
controls
width="640"
height="360"
poster="thumbnail.jpg"
preload="metadata"
playsinline>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
<track kind="captions" src="captions.vtt" srclang="en" label="English" default>
<p>Your browser doesn't support HTML video. <a href="video.mp4">Download</a>.</p>
</video>
Key Attributes
| Attribute | Effect |
|---|---|
controls |
Show play/pause, volume, timeline |
autoplay |
Auto-start (often blocked; requires muted) |
muted |
Start muted — needed for autoplay policies |
loop |
Repeat playback |
poster |
Image shown before playback |
preload |
none, metadata, or auto |
playsinline |
Prevents fullscreen on iOS |
Autoplay Policy
Browsers block autoplay with sound. Pattern for background video:
<video autoplay muted loop playsinline poster="hero.jpg">
<source src="hero.webm" type="video/webm">
</video>
Always provide a pause control for accessibility — autoplaying video can disorient users.
Audio Element
<audio controls preload="none">
<source src="podcast.mp3" type="audio/mpeg">
<source src="podcast.ogg" type="audio/ogg">
<p>Download the <a href="podcast.mp3">MP3</a>.</p>
</audio>
Use preload="none" for pages with many audio files to save bandwidth.
Captions and Subtitles (<track>)
WebVTT (.vtt) files provide timed text tracks:
WEBVTT
00:00:00.000 --> 00:00:03.000
Welcome to the tutorial.
00:00:03.500 --> 00:00:07.000
Today we'll cover HTML media elements.
<track kind="captions" src="en.vtt" srclang="en" label="English" default>
<track kind="subtitles" src="es.vtt" srclang="es" label="Español">
<track kind="descriptions" src="desc.vtt" srclang="en" label="Audio descriptions">
kind |
Purpose |
|---|---|
captions |
Dialogue + sound effects (deaf/hard of hearing) |
subtitles |
Translation of dialogue |
descriptions |
Narration of visual content |
chapters |
Navigation markers |
Captions are a legal requirement for many public-facing videos (WCAG 1.2.2).
Responsive Images with <picture>
<picture>
<source media="(min-width: 800px)" srcset="hero-large.webp" type="image/webp">
<source media="(min-width: 800px)" srcset="hero-large.jpg">
<source srcset="hero-small.webp" type="image/webp">
<img src="hero-small.jpg" alt="Mountain landscape at sunset" width="800" height="450" loading="lazy">
</picture>
<picture> selects sources by media query and format; <img> is required as fallback.
Embedding with <iframe>
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="Tutorial: HTML Media Elements"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
Security: Always set a descriptive title for screen readers. Use sandbox for untrusted embeds:
<iframe src="https://widget.example.com" sandbox="allow-scripts allow-same-origin" title="Weather widget"></iframe>
Lazy Loading Media
<img src="photo.jpg" alt="..." loading="lazy" decoding="async">
<iframe src="..." loading="lazy" title="..."></iframe>
loading="lazy" defers off-screen media. Don’t lazy-load above-the-fold hero images — use fetchpriority="high" instead.
JavaScript Media API
const video = document.querySelector('video');
video.addEventListener('play', () => console.log('Playing'));
video.addEventListener('pause', () => console.log('Paused'));
video.play(); // returns Promise — may reject if autoplay blocked
video.pause();
video.currentTime = 30; // seek to 30 seconds
Best Practices
- Provide captions for all speech content
- Don’t autoplay with sound — respect user preferences
- Offer download fallback inside
<video>/<audio>for unsupported browsers - Compress media — WebM/VP9 or H.264; appropriate bitrates
- Respect
prefers-reduced-motion— pause decorative video
@media (prefers-reduced-motion: reduce) {
video[autoplay] { display: none; }
}
Troubleshooting
Video won’t autoplay
- Add
mutedandplaysinline; callplay()after user gesture if needed
Captions not showing
- Verify
.vttMIME type (text/vtt) on server - Check
defaultattribute on one<track>
iframe blank or blocked
- Check CSP headers and
X-Frame-Optionson embedded site - Confirm
sandboxpermissions aren’t too restrictive
Media elements make the web rich and interactive — use them accessibly and performantly.