Images, Video, Audio
srcset, picture, lazy loading, captions.
Half of every website's payload is images and video. Getting them right is the single biggest performance win on most sites - and the biggest accessibility miss. Modern HTML has powerful tools for responsive images, modern formats, and native media playback. Let's cover them.
The img element, done right
<img
src="/cat.jpg"
alt="A grey tabby cat curled up on a windowsill"
width="600"
height="400"
/>Five attributes worth knowing on every <img>:
src- the URL.alt- text alternative. Required for accessibility. We'll dig in below.width+height- the image's intrinsic dimensions. Setting these prevents layout shift as the image loads. Browsers reserve the space immediately.loading="lazy"- defer loading until the image is near the viewport. Free performance win for below-the-fold images. Don't use it on the hero image; that one should load eagerly.decoding="async"- let the browser decode the image off the main thread.
Alt text: the most-misunderstood attribute
alt is text that replacesthe image for users who can't see it (screen reader users, slow connections, broken URLs). It is not a caption. It is not a tooltip. It is what someone hearing the page would hear in place of the image.
- Informational image: describe what it conveys.
alt="Q1 revenue chart showing 40% growth". - Decorative image: use
alt=""(empty). Screen readers skip it. Don'tomit the attribute entirely; that's a different signal. - Image of text: alt = the text itself. Better yet, stop using images of text.
- Functional image (icon-only button, logo link): alt = what activating it does. Logo:
alt="Acme home".
alt="A grey tabby cat".Responsive images: srcset and sizes
A 4000-pixel-wide image is wasted on a phone. The browser needs hints to pick the right version. That's what srcset and sizes do.
<img
src="/photo-800.jpg"
srcset="
/photo-400.jpg 400w,
/photo-800.jpg 800w,
/photo-1600.jpg 1600w
"
sizes="(max-width: 600px) 100vw, 50vw"
alt="A skyline at dusk"
/>Read it as: "Here are three versions of the image at 400px, 800px, and 1600px wide. The image will display at full viewport width on small screens, and half the viewport width otherwise. Browser, pick whichever file fits best." The browser does the math, including device pixel ratio (Retina displays).
The picture element (art direction)
srcset serves different sizes of the same image. <picture> serves different images entirely based on conditions - useful when you want a wide crop on desktop and a tighter portrait crop on mobile.
<picture>
<source media="(min-width: 800px)" srcset="/wide.jpg" />
<source media="(min-width: 400px)" srcset="/medium.jpg" />
<img src="/small.jpg" alt="A team photo" />
</picture>The browser walks the <source>s in order, picks the first one whose media matches, and uses its srcset. If none match, it falls back to the <img>. That trailing <img> is required; that's what the browser actually renders.
Modern image formats
JPEG and PNG are 30 years old. They still work, but newer formats are dramatically smaller for the same quality.
- WebP - supported everywhere. About 25-35% smaller than JPEG/PNG. A safe default.
- AVIF - newer. Even smaller (~50% vs JPEG) at the same quality. Encoding is slower; decoding is fine. Falls back gracefully via
<picture>. - SVG - vector. Perfect for icons, logos, and illustrations. Scales infinitely and stays tiny.
<picture>
<source type="image/avif" srcset="/photo.avif" />
<source type="image/webp" srcset="/photo.webp" />
<img src="/photo.jpg" alt="..." />
</picture>The browser uses the first format it understands. AVIF for modern browsers, WebP for slightly older, JPEG for everything.
Video and audio
<video controls width="640" poster="/preview.jpg">
<source src="/movie.webm" type="video/webm" />
<source src="/movie.mp4" type="video/mp4" />
<track kind="captions" src="/movie.en.vtt" srclang="en" label="English" default />
Your browser doesn't support video.
</video>
<audio controls src="/podcast.mp3"></audio>Notes worth remembering:
controlsshows the native play/pause UI. Without it, you get a static frame and you'll need JS.posteris the thumbnail shown before playback starts.- Multiple
<source>s let the browser pick a format it can play. WebM first (smaller), MP4 as fallback. <track kind="captions">adds subtitles. Use a .vtt (WebVTT) file. Captions are not optional for accessibility.- Autoplay video is widely blocked by browsers unless it's muted. Use
autoplay muted playsinlineif you must.
loading="lazy" to anything below the fold. Your Core Web Vitals will thank you.Quick quiz: alt text decisions
You're adding a decorative pattern image as background flair. What's the right alt?
Recap
- Always set
alt. Describe meaningful images; usealt=""for decoration. - Set
widthandheightto prevent layout shift. Useloading="lazy"for below-the-fold images. srcset+sizeslet the browser pick the right resolution.<picture>handles art direction and format fallbacks.- Prefer AVIF > WebP > JPEG/PNG. Use SVG for icons and logos.
<video>needscontrolsto play. Add<track>for captions.- Autoplay only works muted in modern browsers.