TechLead

Images, Media, and Embeds

Responsive images, audio/video, and iframe embeds

HTML provides native elements for embedding video, audio, images, and external content. Using the right element gives you built-in browser controls, accessibility, and better performance than plugin-based approaches.

The <video> Element

Provide multiple source formats for cross-browser support. Browsers pick the first format they understand.

<video
  width="800"
  height="450"
  controls
  muted
  preload="metadata"
  poster="thumbnail.jpg"
>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4"  type="video/mp4">
  <track kind="subtitles" src="subs-en.vtt" srclang="en" label="English" default>
  <p>Your browser does not support HTML video. <a href="video.mp4">Download it</a>.</p>
</video>
  • controls — show native play/pause/volume UI
  • autoplay muted — browsers only allow autoplay when muted
  • preload="none|metadata|auto" — controls how eagerly the browser fetches
  • poster — image displayed before the video loads
  • <track> — captions/subtitles in WebVTT format (required for accessibility)

The <audio> Element

<audio controls preload="none">
  <source src="podcast.opus" type="audio/ogg; codecs=opus">
  <source src="podcast.mp3"  type="audio/mpeg">
  <track kind="captions" src="captions.vtt" srclang="en">
</audio>

Responsive Images with <picture>

The <picture> element lets you serve different images based on screen size or format support. The browser picks the first matching <source>; <img> is the fallback.

<picture>
  <!-- Modern format for supporting browsers -->
  <source
    srcset="hero-800.avif 800w, hero-1600.avif 1600w"
    sizes="(max-width: 600px) 100vw, 50vw"
    type="image/avif"
  >
  <source
    srcset="hero-800.webp 800w, hero-1600.webp 1600w"
    sizes="(max-width: 600px) 100vw, 50vw"
    type="image/webp"
  >
  <!-- Fallback -->
  <img src="hero-800.jpg" alt="Mountain landscape at sunrise" width="800" height="450" loading="lazy">
</picture>

Embedding External Content with <iframe>

<!-- YouTube embed -->
<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/VIDEO_ID"
  title="Video title"
  loading="lazy"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
  allowfullscreen
></iframe>

<!-- Google Map -->
<iframe
  src="https://maps.google.com/maps?q=..."
  loading="lazy"
  title="Office location map"
></iframe>

Performance and Lazy Loading

<!-- Native lazy loading for images and iframes -->
<img src="image.jpg" alt="..." loading="lazy" decoding="async">
<iframe src="..." loading="lazy" title="..."></iframe>

<!-- Facade pattern for heavy embeds (load on interaction) -->
<div id="youtube-facade" style="cursor:pointer" onclick="loadYouTube(this)"
  data-id="VIDEO_ID"
  style="background: url(thumbnail.jpg) center/cover"
  aria-label="Play video"
  role="button" tabindex="0"
></div>

Best Practices

  • Always include alt on <img> and title on <iframe>
  • Add <track kind="captions"> to all video and audio — required for WCAG 2.1 AA
  • Use loading="lazy" on below-the-fold images and iframes
  • Prefer <picture> with AVIF/WebP sources over a single JPEG
  • Set explicit width and height on images to prevent layout shift (CLS)

Continue Learning