HTML Video Element
Video is the richest thing you can put on a page. It can teach a skill step by step, show a product from every side, or tell a story. The <video> element embeds it directly, with the browser's own player, so there is nothing to install and no outside service needed.
It works almost like <audio>, with a few extra things to think about: the size, the poster picture, the file weight, and what to do when there is no sound or no picture to rely on.
What You Will Learnβ
- Embedding video with
<video>,src, andcontrols - The attributes:
width,height,poster,preload,muted,loop,playsinline, andautoplay - Choosing MP4 or WebM, and compressing files
- Avoiding layout jumps with the right size
- Background videos, done safely
- The JavaScript API, accessibility, and global notes
The Basicsβ
- HTML Code
- Browser Output
<video
src="lesson.mp4"
width="640"
height="360"
poster="cover.jpg"
controls
playsinline
preload="metadata"
>
Your browser cannot play this video.
<a href="lesson.mp4">Download it (MP4, 18 MB)</a>.
</video>
paused: truevideoWidth Γ videoHeight: not loaded yet- Latest events: none yet
This is a real video element showing a live, animated canvas (so it has no fixed length). Press play, change the width, and toggle the sound.
The demo is a real <video> element. So you can try it without a file, it plays a small animated picture drawn by the page. Your own videos work the same way, except that they have a fixed length.
Attributesβ
| Attribute | What it does | Advice |
|---|---|---|
src | The address of the video file | Or use source elements for several formats (see Source) |
controls | Shows the player | Almost always include it |
width, height | The size, in pixels, with no units | Set both, so the browser reserves space |
poster | A picture shown before the video plays | Use a clear, light image |
preload | none, metadata, or auto | Prefer metadata or none |
muted | Starts silent | Required for any autoplay attempt |
autoplay | Tries to start by itself | Avoid, except for silent background clips |
loop | Repeats when finished | Only for short, silent, decorative clips |
playsinline | Plays inside the page on iPhones | Add it, so video does not jump to full screen |
crossorigin | How to fetch from another site | Needed for captions from another domain |
Try It: Build the Tagβ
Change the attributes and the shape of the video, and read the advice.
- HTML Code
- Browser Output
<!-- A polite lesson video -->
<video src="lesson.mp4" width="640" height="360"
poster="cover.jpg" controls playsinline preload="metadata"></video>
<!-- A silent decorative loop (see "Background videos" below) -->
<video src="bg.mp4" width="640" height="360"
autoplay muted loop playsinline></video>
Size and Layout Jumpsβ
Without a size, the browser does not know how tall the video will be until it has downloaded the start of the file. The page then jumps as the video box appears, which is annoying, and pushes the text the visitor was reading.
The cure: always set width and height. They tell the browser the shape (the aspect ratio), even if CSS later changes the real size.
<video src="lesson.mp4" width="640" height="360" controls></video>
video {
max-width: 100%; /* never wider than its container */
height: auto; /* keep the shape */
}
You can also set aspect-ratio: 16 / 9 in CSS. For full responsive techniques, such as videos that fill their column, see Responsive Video.
Choosing a Formatβ
| Format | Typical file | Notes |
|---|---|---|
| MP4 (H.264 video, AAC audio) | .mp4 | The safest choice. Plays almost everywhere |
| WebM (VP9 or AV1 video, Opus audio) | .webm | Often smaller at the same quality. Check support in the browsers you need |
| Ogg (Theora) | .ogv | Old. Rarely needed today |
For most sites, one well-made MP4 is enough. To also offer a smaller WebM, list both with <source>, and the browser takes the first it can play. See Source. Support changes over time, so test before you decide.
Make the File Smallβ
Raw video from a phone or screen recorder can be enormous. Compress it before it goes on the web. A common tool is FFmpeg:
# MP4: widely compatible, "+faststart" lets it begin playing before it fully downloads
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset slow \
-c:a aac -b:a 128k -movflags +faststart output.mp4
# WebM: often smaller
ffmpeg -i input.mov -c:v libvpx-vp9 -crf 32 -b:v 0 \
-c:a libopus output.webm
Higher -crf numbers give smaller files and lower quality. Try a few values and watch a clip. Also trim the video, and lower the resolution if it is only shown small: a 4K video in a 640-pixel box is wasted data.
The Posterβ
A poster is the picture shown before the video starts. Without one, the box can be black or empty until the browser loads a frame.
<video src="lesson.mp4" poster="cover.jpg" controls width="640" height="360"></video>
- Use a clear, representative frame, not a blurry or dark one.
- Keep the poster file small (a compressed JPEG or WebP).
- With
preload="none", the poster is all the visitor sees, so it matters even more. - The poster is not announced like an image. Describe the video in a nearby heading, or with
aria-label.
Background Videos, Done Safelyβ
A silent, looping clip behind a heading is a popular design. It can be done kindly:
<video id="bg" src="waves.mp4" autoplay muted loop playsinline
aria-hidden="true" width="1280" height="720"></video>
<button type="button" id="bg-toggle">Pause background video</button>
const bg = document.getElementById("bg");
const toggle = document.getElementById("bg-toggle");
// Respect people who ask for less motion
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
bg.removeAttribute("autoplay");
bg.pause();
}
toggle.addEventListener("click", () => {
if (bg.paused) {
bg.play();
toggle.textContent = "Pause background video";
} else {
bg.pause();
toggle.textContent = "Play background video";
}
});
The rules for good manners:
- It must be muted (or browsers block it) and use
playsinline. - It must carry no essential information. Mark it
aria-hidden="true". - Give visitors a pause button. Moving content that lasts more than 5 seconds needs one.
- Respect
prefers-reduced-motion. - Keep text readable over it, with enough contrast.
- Keep the file tiny, and consider a still image on slow connections.
Controlling Video with JavaScriptβ
The API is the same as for audio, with a few extras:
const video = document.querySelector("video");
video.play().catch(() => console.log("Blocked: show a Play button"));
video.pause();
video.currentTime = 12;
video.playbackRate = 1.25;
video.requestFullscreen(); // full screen
video.requestPictureInPicture?.(); // a floating window, where supported
console.log(video.videoWidth, video.videoHeight); // the real size, once loaded
video.addEventListener("ended", () => console.log("Finished"));
More on building your own controls is in Media Controls.
Captions and Alternativesβ
A video usually needs three kinds of access:
| For people who⦠| Provide |
|---|---|
| Cannot hear, or cannot play sound | Captions (track kind="captions"), see Captions |
| Read another language | Subtitles, see Subtitles |
| Cannot see the picture | Narration that describes what happens, or an audio description track or version |
| Prefer to read, or cannot play video | A transcript on the page |
The attached text files are added with <track>. The full checklist is in Accessible Media.
Accessibility at a Glanceβ
- Include
controlsthat work with the keyboard. The built-in ones do. - Add captions to every video with speech or meaningful sound.
- Do not autoplay with sound, and give any moving background a pause button.
- Avoid flashing more than three times in a second.
- Describe the video with a heading or
aria-label, so people know what it is before they play it. - Give a transcript or text summary.
- Do not put important information only in the picture. Say it in the narration too.
- Keep contrast for any text drawn over the video.
Security and Privacy Notesβ
- Videos can be downloaded by anyone who can play them. Hiding the controls or blocking right-click does not protect a file. Private video must be served only to authorised users, by the server.
- Own the rights to every clip and soundtrack.
- Use HTTPS to avoid mixed content blocking.
- Third-party embeds (for example in an
iframe) can track your visitors. Check what they load, and ask for consent where required. - User uploads need care: check the type and size on the server, and re-encode if you can. Never trust the file name or the declared type.
- Do not reveal private details in a video's file name or poster, such as a customer's name.
Global Audience Notesβ
- Video is heavy. Many visitors have slow or metered connections. Compress files, use
preload="metadata"ornone, and show the file size on download links. - Offer captions, and subtitles in more languages. See Subtitles.
- Do not rely on one language in on-screen text. Put key words in captions too, so they can be translated.
- Avoid idioms and humour that do not translate, or explain them in the transcript.
- Test on small, old phones and on a slow network.
- Use
playsinline, because many visitors watch on phones.
Common Mistakes to Avoidβ
- Leaving out
controls. - No
widthandheight, so the page jumps. - Fixed pixel sizes only, so the video overflows on phones. Use
max-width: 100%. - Autoplaying with sound.
- No captions or transcript.
- Huge, uncompressed files.
- Only one format when you need to support unusual browsers.
- Forgetting
playsinlineon mobile. - No poster, so the box is black.
- A looping background with no pause button.
- Putting essential information only in the picture.
- Assuming a hidden video is private.
Practice Timeβ
Try these in your editor, with a short MP4 you have the right to use:
- Add a
<video controls>withwidthandheight, and play it with the keyboard only. - Add a
posterimage, and compare it with no poster. - Add
max-width: 100%; height: auto;and narrow your browser window. - Set
preload="none"and check the network panel before pressing play. - Compress your video with FFmpeg, and compare the file sizes.
- Add fallback text with a download link.
- Build a muted, looping background clip with a pause button.
- Add the
prefers-reduced-motioncheck, and test it in your system settings. - Add a button that jumps back 10 seconds with
currentTime. - Bonus: use
requestFullscreen()from a custom button, and test with the keyboard.
Quick Recapβ
Click a question to check your answer.
1. Why set width and height on a video?
They tell the browser the shape of the video before it loads, so it can reserve the space. Without them, the page jumps when the video appears.
2. What is poster for?
It is the picture shown before the video plays. A clear, small poster stops the box from looking black or empty.
3. When is autoplay acceptable?
Only for short, silent, decorative clips that carry no essential information, with muted and playsinline, a pause button, and respect for reduced-motion settings. Never with sound.
4. Which format is the safest?
MP4 with H.264 video and AAC audio plays almost everywhere. WebM can be smaller, and both can be offered with source.
5. What does playsinline do?
On iPhones and some mobile browsers, it keeps the video playing inside the page, instead of jumping to full screen.
6. How do you make a video accessible?
Add captions, provide a transcript, describe visual-only information in the narration or with an audio description, avoid flashing, and make sure the controls work with a keyboard.
Key Takeawaysβ
<video controls src="β¦">embeds video with a full, keyboard-friendly player.- Always set
widthandheight, and usemax-width: 100%; height: auto;in CSS. - Add a
poster,playsinline, and a sensiblepreload. - Use MP4 for safety, compress your files, and offer WebM with
sourceif you need to. - Never autoplay with sound. A silent background loop needs a pause button and must respect reduced motion.
- Provide captions, subtitles, and a transcript, using
track. - Hidden video is not private, and embedded players can track visitors.
- Plan for slow connections, small phones, and many languages.
Next, learn how to offer several formats in Source, or return to the Audio and Video overview.