Skip to main content

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, and controls
  • The attributes: width, height, poster, preload, muted, loop, playsinline, and autoplay
  • 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​

index.html
<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>

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​

AttributeWhat it doesAdvice
srcThe address of the video fileOr use source elements for several formats (see Source)
controlsShows the playerAlmost always include it
width, heightThe size, in pixels, with no unitsSet both, so the browser reserves space
posterA picture shown before the video playsUse a clear, light image
preloadnone, metadata, or autoPrefer metadata or none
mutedStarts silentRequired for any autoplay attempt
autoplayTries to start by itselfAvoid, except for silent background clips
loopRepeats when finishedOnly for short, silent, decorative clips
playsinlinePlays inside the page on iPhonesAdd it, so video does not jump to full screen
crossoriginHow to fetch from another siteNeeded for captions from another domain

Try It: Build the Tag​

Change the attributes and the shape of the video, and read the advice.

index.html
<!-- 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​

FormatTypical fileNotes
MP4 (H.264 video, AAC audio).mp4The safest choice. Plays almost everywhere
WebM (VP9 or AV1 video, Opus audio).webmOften smaller at the same quality. Check support in the browsers you need
Ogg (Theora).ogvOld. 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:

terminal
# 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:

  1. It must be muted (or browsers block it) and use playsinline.
  2. It must carry no essential information. Mark it aria-hidden="true".
  3. Give visitors a pause button. Moving content that lasts more than 5 seconds needs one.
  4. Respect prefers-reduced-motion.
  5. Keep text readable over it, with enough contrast.
  6. 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 soundCaptions (track kind="captions"), see Captions
Read another languageSubtitles, see Subtitles
Cannot see the pictureNarration that describes what happens, or an audio description track or version
Prefer to read, or cannot play videoA transcript on the page

The attached text files are added with <track>. The full checklist is in Accessible Media.

Accessibility at a Glance​

  • Include controls that 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" or none, 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​

  1. Leaving out controls.
  2. No width and height, so the page jumps.
  3. Fixed pixel sizes only, so the video overflows on phones. Use max-width: 100%.
  4. Autoplaying with sound.
  5. No captions or transcript.
  6. Huge, uncompressed files.
  7. Only one format when you need to support unusual browsers.
  8. Forgetting playsinline on mobile.
  9. No poster, so the box is black.
  10. A looping background with no pause button.
  11. Putting essential information only in the picture.
  12. Assuming a hidden video is private.

Practice Time​

Try these in your editor, with a short MP4 you have the right to use:

  1. Add a <video controls> with width and height, and play it with the keyboard only.
  2. Add a poster image, and compare it with no poster.
  3. Add max-width: 100%; height: auto; and narrow your browser window.
  4. Set preload="none" and check the network panel before pressing play.
  5. Compress your video with FFmpeg, and compare the file sizes.
  6. Add fallback text with a download link.
  7. Build a muted, looping background clip with a pause button.
  8. Add the prefers-reduced-motion check, and test it in your system settings.
  9. Add a button that jumps back 10 seconds with currentTime.
  10. 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 width and height, and use max-width: 100%; height: auto; in CSS.
  • Add a poster, playsinline, and a sensible preload.
  • Use MP4 for safety, compress your files, and offer WebM with source if 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.