NEWMeet the new Video Gallery — YouTube, TikTok, Instagram Reels, Vimeo and Twitch in one widget.

Find a widget for you

You can use our widgets to accomplish practically any task on your website — increase users' confidence, grow conversion, engage your visitors, provide support, etc.

See All Widgets
GuideVideo Gallery

HTML Video Tag: The Complete Guide with Examples

Updated September 2026 · 26 min read

Short answer

The HTML <video> element plays video files natively. Add src or <source> elements, controls, and optional attributes like autoplay, muted, loop, playsinline, poster and preload.

Key takeaways

  • Use <video> with an MP4 (H.264/AAC) source; add WebM first if you want smaller files.
  • Add controls, a poster and preload="metadata" — autoplay only when muted and inline.
  • Reserve space with aspect-ratio and use object-fit to fit any layout.
  • Add captions with <track> for accessibility.
  • For YouTube or Vimeo use their iframe players; for many videos use a gallery.

Basic example

<video controls width="640" poster="poster.jpg">
  <source src="movie.webm" type="video/webm">
  <source src="movie.mp4" type="video/mp4">
  Your browser does not support HTML5 video.
</video>

Attributes

AttributeWhat it does
controlsShows play, volume and fullscreen controls
autoplayStarts playback automatically (needs muted)
mutedStarts without sound
loopReplays when it ends
playsinlinePlays inline on iPhone
posterImage shown before playback
preloadnone / metadata / auto — how much to load up front
width / heightIntrinsic size (use CSS for responsive)

Responsive video

video{width:100%;height:auto;aspect-ratio:16/9}

Captions

<video controls>
  <source src="movie.mp4" type="video/mp4">
  <track kind="captions" src="captions.vtt" srclang="en" label="English" default>
</video>

Embedding YouTube isn’t the video tag

YouTube and Vimeo videos can’t be played with <video>; use their iframe players — see our YouTube embed code generator.

The no-code way

Need a gallery of YouTube, Vimeo and hosted videos instead of one player? Use a widget.

Try Elfsight Video Gallery →

Formats and browser support

FormatSupportUse it for
MP4 (H.264 + AAC)All modern browsersThe default choice
WebM (VP9 / AV1)All modern browsers except some older Safari versionsSmaller files — offer as an extra <source>
HLS (.m3u8)Native in Safari; others need hls.jsLong videos and live streams

Control the video with JavaScript

const v = document.querySelector("video");
v.play();            // returns a Promise
v.pause();
v.currentTime = 30;  // seek to 0:30
v.muted = true;
v.addEventListener("ended", () => console.log("done"));
v.addEventListener("timeupdate", () => console.log(v.currentTime));

Handle the Promise from play() — it rejects when the browser blocks playback.

Lazy loading and performance

  • preload="none" or "metadata" keeps the initial page light.
  • A poster image shows instantly.
  • Use loading="lazy" on iframes; for <video>, set the src when it scrolls into view.
  • Reserve space with aspect-ratio to avoid layout shift.

Accessibility checklist

  • Add captions with <track kind="captions">.
  • Keep controls unless you provide your own accessible controls.
  • Never autoplay with sound.
  • Provide a transcript for important videos.

Common problems

  1. Video doesn’t play on iPhone

    Add playsinline and muted for autoplay; check the codec is H.264.

  2. Black screen before play

    Add a poster image.

  3. Wrong size on mobile

    Use width:100%; height:auto; aspect-ratio.

  4. Large file loads slowly

    Compress it or stream it from a video platform.

How the browser picks a source

The browser reads the <source> elements from top to bottom and plays the first one it supports. That’s why you list the smaller, more modern format first (WebM) and the universally supported one (MP4) second. The type attribute lets the browser skip files it can’t play without downloading them — always include it. Text placed inside <video> after the sources is shown only by browsers that don’t support video at all.

<video controls preload="metadata" poster="poster.jpg">
  <source src="clip.webm" type='video/webm; codecs="vp9, opus"'>
  <source src="clip.mp4"  type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
  <a href="clip.mp4">Download the video</a>
</video>

Fit video into any layout

Use CSS to control how the video fills its box. object-fit: cover fills the area and crops the edges — ideal for hero sections. object-fit: contain shows the whole frame with bars. Combine it with aspect-ratio to reserve space before the file loads and prevent layout shift.

.video-box{aspect-ratio:16/9;width:100%}
.video-box video{width:100%;height:100%;object-fit:cover}

/* vertical clips */
.video-vertical{aspect-ratio:9/16;max-width:360px}

Picture-in-picture and fullscreen

Modern browsers let you move a video into a floating window or fullscreen from JavaScript — both need a user gesture such as a click.

const v = document.querySelector("video");

pipButton.onclick = async () => {
  if (document.pictureInPictureElement) await document.exitPictureInPicture();
  else await v.requestPictureInPicture();
};

fullButton.onclick = () => v.requestFullscreen();

Add disablepictureinpicture to the element if you don’t want the browser’s own PiP button.

Track video engagement

The video element fires events you can send to your analytics tool. Track starts, completions and progress milestones — not every timeupdate, which fires several times per second.

const v = document.querySelector("video");
const sent = new Set();
const track = (name) => window.gtag && gtag("event", name, { video_title: v.dataset.title });

v.addEventListener("play", () => track("video_start"), { once: true });
v.addEventListener("ended", () => track("video_complete"));
v.addEventListener("timeupdate", () => {
  const p = Math.floor((v.currentTime / v.duration) * 4) * 25; // 25, 50, 75
  if (p && p < 100 && !sent.has(p)) { sent.add(p); track("video_progress_" + p); }
});

Video tag, iframe or gallery?

The video tag is the right tool for your own short files: product loops, hero backgrounds, short explainers you host on a CDN. For videos on YouTube or Vimeo, use their iframe players — they handle streaming, quality switching and captions. When you need many videos, feeds that update themselves, or a mix of platforms, a gallery widget saves you from building playlists, popups and layouts by hand.

Frequently asked questions

How do I embed a video in HTML?

Use <video controls> with a <source> pointing to an MP4 file.

Why doesn’t autoplay work on my video tag?

Add muted (and playsinline for iPhone).

Can I play YouTube videos with the video tag?

No. Use the YouTube iframe embed.

What is the poster attribute?

An image shown before the video plays.

Can I use the video tag for YouTube?

No — YouTube needs its iframe player.

Which is better, MP4 or WebM?

MP4 (H.264) works everywhere; WebM is often smaller. Offer both, WebM first.

How do I stop the video from downloading on page load?

Use preload="none" or "metadata" and a poster image.

What does playsinline do?

On iPhone it keeps the video inside the page instead of switching to fullscreen. It’s required for inline autoplay.

How do I make a video loop only part of the clip?

Listen to timeupdate and set currentTime back to your start point when it passes the end point — or export the section as its own file.

Can I play a video from Google Drive in the video tag?

Not reliably. Drive share links open Drive’s viewer, not the file. Host the MP4 on your server, a CDN or cloud storage with a direct link.

How do I add chapters?

Add a <track kind="chapters"> with a WebVTT file; support for showing chapters varies by browser, so many sites also list chapters as buttons that set currentTime.

Official documentation

Related

Put your videos on your website

Create a free video gallery in minutes.

Create Widget for Free