Images, Figures, and Multimedia
Images, video, and audio make pages engaging and informative. HTML5 introduced native elements for all of these, along with powerful tools for responsive images, accessibility, and performance optimisation.
1. The <img> Element
The <img> element embeds an image into an HTML page. It is a void element — it has no closing tag.
<img
src="images/mountain.jpg"
alt="Snow-covered mountain at sunrise"
width="800"
height="500"
loading="lazy"
>
All Important <img> Attributes
| Attribute | Purpose | Example value |
|---|---|---|
src | URL or path to the image file | "images/photo.jpg" |
alt | Text description (required) | "A red barn in a field" |
width | Display width in CSS pixels | "800" |
height | Display height in CSS pixels | "500" |
loading | When to load the image | "lazy" or "eager" |
srcset | List of image sources and widths | "img-400.jpg 400w, img-800.jpg 800w" |
sizes | Hint for how wide the image will display | "(max-width: 600px) 100vw, 50vw" |
decoding | How the browser decodes the image | "async" |
fetchpriority | Priority for loading | "high" or "low" |
crossorigin | CORS setting for external images | "anonymous" |
2. The alt Attribute – Accessibility First
The alt attribute is one of the most important things you can write in HTML. It serves multiple purposes:
- Screen readers read it aloud to visually impaired users
- Browsers display it when the image fails to load or the path is wrong
- Search engines use it to understand image content (SEO)
- Slow connections let users decide whether to wait for the image
Writing Good Alt Text
<!-- ❌ Bad — no information -->
<img src="dog.jpg" alt="image">
<!-- ❌ Bad — keyword stuffing -->
<img src="dog.jpg" alt="dog puppy canine pet animal photo picture">
<!-- ✅ Good — descriptive and specific -->
<img src="dog.jpg" alt="A golden retriever puppy playing with a ball in the garden">
<!-- ✅ Good — describes the information the image conveys -->
<img src="bar-chart.png" alt="Bar chart showing sales grew 40% between January and March">
Decorative Images
If an image is purely decorative and adds no information, use an empty alt so screen readers skip it entirely:
<!-- Decorative divider — screen readers will ignore this -->
<img src="wave-divider.svg" alt="">
Never omit the
altattribute entirely. Missingaltmakes screen readers read the full filename, which is confusing.
3. Lazy Loading
loading="lazy" tells the browser to defer loading the image until it is near the viewport. This speeds up initial page load significantly.
<!-- Load immediately (for images above the fold) -->
<img src="hero.jpg" alt="Hero banner" loading="eager">
<!-- Defer loading until near viewport (for images further down the page) -->
<img src="product-photo.jpg" alt="Product photo" loading="lazy">
- Use
loading="eager"(or omitloading) for the largest visible image on first load — especially the hero image - Use
loading="lazy"for all images that are below the fold
fetchpriority for the Hero Image
The browser's resource scheduler may not know which image is most important. You can give it a hint:
<!-- Highest loading priority — ideal for the main hero image -->
<img
src="hero.jpg"
alt="Students collaborating on code"
loading="eager"
fetchpriority="high"
>
4. Specifying Dimensions to Prevent Layout Shift
Always provide width and height on images. The browser reserves space before the image loads, preventing Cumulative Layout Shift (CLS) — a Core Web Vitals metric.
<!-- ✅ Browser reserves 1200×630 px before image loads -->
<img src="banner.jpg" alt="Nandhoo banner" width="1200" height="630">
<!-- ❌ No dimensions — page jumps when the image loads -->
<img src="banner.jpg" alt="Nandhoo banner">
The width and height attributes set the aspect ratio used for layout. CSS can then override the actual display size:
img {
width: 100%;
height: auto; /* maintains aspect ratio */
}
5. Responsive Images with srcset and sizes
Different screen sizes need different image resolutions. The srcset and sizes attributes let the browser choose the best one automatically.
srcset — Provide Multiple Sizes
<img
src="mountain-800.jpg"
srcset="
mountain-400.jpg 400w,
mountain-800.jpg 800w,
mountain-1200.jpg 1200w,
mountain-2400.jpg 2400w
"
alt="Mountain landscape"
>
Each entry is <file> <width>w. The w means pixel width of that file.
sizes — Tell the Browser How the Image Will Display
<img
src="mountain-800.jpg"
srcset="
mountain-400.jpg 400w,
mountain-800.jpg 800w,
mountain-1200.jpg 1200w
"
sizes="
(max-width: 480px) 100vw,
(max-width: 960px) 50vw,
800px
"
alt="Mountain landscape"
>
How the browser uses sizes:
- Checks which media condition matches the current viewport
- Determines the display size (e.g.
50vwof a 900px viewport = 450px) - Picks the smallest
srcsetentry that is wide enough - Downloads only that one image
This means a mobile user on a 375px screen downloads a small file instead of a 2400px image.
6. <figure> and <figcaption>
Use <figure> to wrap any self-contained piece of media (image, video, code, chart) that is referenced from the main text. Use <figcaption> to add a caption.
<figure>
<img src="neural-network.png" alt="Diagram of a three-layer neural network">
<figcaption>
Figure 1: A three-layer neural network with one input layer, one hidden layer, and one output layer.
</figcaption>
</figure>
Why Use <figure> Instead of Just <img>?
- Semantically groups media with its caption
- Screen readers announce it as a figure
- The caption is visually and semantically associated with the image
- You can move or float the whole block as a unit with CSS
Multiple Images in One Figure
<figure>
<img src="before.jpg" alt="Homepage design before redesign">
<img src="after.jpg" alt="Homepage design after redesign">
<figcaption>Before and after the Nandhoo homepage redesign.</figcaption>
</figure>
7. Image Formats — Choosing the Right One
| Format | Best for | Transparency | Animation | Notes |
|---|---|---|---|---|
| JPEG / JPG | Photos, complex colour gradients | No | No | Lossy — small file, some quality loss |
| PNG | Graphics, screenshots, logos, icons | Yes (alpha) | No | Lossless — larger files |
| GIF | Simple animations | Yes (1-bit) | Yes | Limited to 256 colours |
| SVG | Icons, logos, illustrations, maps | Yes | Yes (CSS) | Vector — scales to any size with no quality loss |
| WebP | Everything — replaces JPEG and PNG | Yes | Yes | ~25–35% smaller than JPEG at same quality |
| AVIF | Modern browsers — best compression | Yes | Yes | Even smaller than WebP, slower encoding |
Format Decision Guide
Is it a photo?
→ Yes: Use WebP (with JPEG fallback)
Is it an icon or logo?
→ Yes: Use SVG if possible
Does it need a transparent background?
→ Yes: Use WebP or PNG
Does it need to animate?
→ Yes: Use WebP animation or CSS/JavaScript animation instead of GIF
Need maximum compatibility with older browsers?
→ Yes: Stick with JPEG and PNG
8. The <picture> Element — Art Direction and Format Switching
The <picture> element gives you full control: serve different crops for different screen sizes (art direction), or serve different formats depending on browser support.
Format Switching (WebP with JPEG Fallback)
<picture>
<!-- Modern browsers load the WebP version -->
<source srcset="photo.webp" type="image/webp">
<!-- Older browsers fall back to JPEG -->
<img src="photo.jpg" alt="Students working together on a coding project">
</picture>
The browser tries each <source> in order and picks the first one it supports. The <img> at the bottom is always the fallback.
Art Direction (Different Crops for Different Viewports)
<picture>
<!-- Wide screens: full landscape panorama -->
<source
srcset="hero-landscape.jpg"
media="(min-width: 900px)"
>
<!-- Medium screens: square crop -->
<source
srcset="hero-square.jpg"
media="(min-width: 480px)"
>
<!-- Small screens: tight portrait crop -->
<img src="hero-portrait.jpg" alt="Teenager learning to code">
</picture>
Combining Both: Format and Art Direction
<picture>
<source
srcset="hero-landscape.avif"
type="image/avif"
media="(min-width: 900px)"
>
<source
srcset="hero-landscape.webp"
type="image/webp"
media="(min-width: 900px)"
>
<source
srcset="hero-portrait.webp"
type="image/webp"
>
<img src="hero-portrait.jpg" alt="Teenager learning to code">
</picture>
9. Inline SVG
SVGs can be embedded directly in HTML, giving full CSS and JavaScript control over every part of the graphic.
<!-- External SVG file — simple, cacheable -->
<img src="logo.svg" alt="Nandhoo logo">
<!-- Inline SVG — fully controlled with CSS/JS -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
width="80"
height="80"
role="img"
aria-label="Simple smiley face icon"
>
<circle cx="50" cy="50" r="45" fill="#FFD700" />
<circle cx="35" cy="40" r="5" fill="#333" />
<circle cx="65" cy="40" r="5" fill="#333" />
<path d="M 30 65 Q 50 80 70 65" stroke="#333" stroke-width="3" fill="none" />
</svg>
When to Use Inline SVG
- When you need to animate specific parts of the icon with CSS
- When you need to change colours on hover or via JavaScript
- When you need to make the icon fully accessible with
aria-label
10. The <video> Element
HTML5's <video> element embeds video without any plugin.
<video
src="intro.mp4"
controls
width="800"
height="450"
poster="intro-thumbnail.jpg"
>
Your browser does not support HTML5 video.
</video>
Multiple Source Formats for Compatibility
<video
controls
width="800"
height="450"
poster="intro-thumbnail.jpg"
preload="metadata"
>
<source src="intro.webm" type="video/webm">
<source src="intro.mp4" type="video/mp4">
<!-- Subtitles / captions track -->
<track
kind="subtitles"
src="intro-en.vtt"
srclang="en"
label="English"
default
>
<p>Your browser does not support HTML5 video.
<a href="intro.mp4">Download the video.</a>
</p>
</video>
<video> Attributes
| Attribute | What it does |
|---|---|
controls | Shows the browser's native play/pause/volume controls |
autoplay | Starts playing as soon as possible (muted is required for autoplay in most browsers) |
muted | Starts with audio muted |
loop | Repeats indefinitely |
poster | Image shown before the video plays |
preload | "none" / "metadata" / "auto" — how much to buffer upfront |
width / height | Reserves layout space and sets aspect ratio |
playsinline | Plays inline on iOS instead of going fullscreen |
Autoplay Background Video (Accessible)
<video
autoplay
muted
loop
playsinline
poster="hero-background.jpg"
aria-hidden="true"
>
<source src="hero-background.webm" type="video/webm">
<source src="hero-background.mp4" type="video/mp4">
</video>
aria-hidden="true" hides decorative background videos from screen readers.
11. The <audio> Element
The <audio> element embeds sound files with native browser controls.
<audio controls>
<source src="podcast.ogg" type="audio/ogg">
<source src="podcast.mp3" type="audio/mpeg">
<p>Your browser does not support HTML5 audio.
<a href="podcast.mp3">Download the episode.</a>
</p>
</audio>
<audio> Attributes
| Attribute | What it does |
|---|---|
controls | Shows native play/pause/volume UI |
autoplay | Begins playing when page loads (avoid — bad for accessibility and user experience) |
muted | Starts muted |
loop | Plays repeatedly |
preload | "none" / "metadata" / "auto" |
Audio File Formats
| Format | MIME type | Browser support |
|---|---|---|
| MP3 | audio/mpeg | Universal |
| OGG Vorbis | audio/ogg | Firefox, Chrome |
| WAV | audio/wav | All major browsers |
| AAC | audio/aac | Safari, Chrome, Edge |
| WebM audio | audio/webm | Chrome, Firefox |
Providing both OGG and MP3 covers all modern browsers.
12. Captions and Subtitles with <track>
The <track> element adds timed text tracks to <video> or <audio>. It uses the WebVTT format (.vtt files).
<video src="tutorial.mp4" controls width="800" height="450">
<track kind="subtitles" src="subtitles-en.vtt" srclang="en" label="English" default>
<track kind="subtitles" src="subtitles-fr.vtt" srclang="fr" label="Français">
<track kind="captions" src="captions-en.vtt" srclang="en" label="English (captions)">
<track kind="descriptions" src="descriptions.vtt" srclang="en" label="Audio descriptions">
</video>
Track kind Values
| Kind | Purpose |
|---|---|
subtitles | Translations of spoken dialogue |
captions | Subtitles + non-speech audio cues for deaf/hard-of-hearing users |
descriptions | Text descriptions of visual content for blind users |
chapters | Named chapter markers |
metadata | Data used by scripts |
A Basic WebVTT File
WEBVTT
00:00:00.000 --> 00:00:03.500
Welcome to the HTML5 multimedia chapter.
00:00:03.500 --> 00:00:07.000
In this section we will cover images, video, and audio.
00:00:07.000 --> 00:00:11.000
Every video should have captions for accessibility.
13. Embedding External Media with <iframe>
<iframe> embeds another web page or service inside your page — commonly used for YouTube, Google Maps, and Spotify.
<!-- YouTube video embed -->
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
title="Introduction to HTML5 — video lesson"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
loading="lazy"
></iframe>
Making iframes Responsive
Iframes have a fixed size by default. Wrap them to make them responsive:
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
<iframe
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
title="HTML5 tutorial"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
frameborder="0"
allowfullscreen
loading="lazy"
></iframe>
</div>
padding-bottom: 56.25% creates a 16:9 aspect ratio (9 ÷ 16 = 0.5625).
Security: sandbox and referrerpolicy
<iframe
src="https://example-user-content.com"
sandbox="allow-scripts allow-same-origin"
referrerpolicy="no-referrer"
title="User submitted content"
></iframe>
sandboxrestricts what the iframe can do (form submission, scripts, popups, etc.)referrerpolicy="no-referrer"prevents your URL from being sent to the embedded page
14. Image Maps (Clickable Areas)
An image map defines clickable hotspots on a single image.
<img
src="world-map.jpg"
alt="World map with clickable regions"
usemap="#world-regions"
width="800"
height="400"
>
<map name="world-regions">
<area shape="rect" coords="50,50,200,200" href="europe.html" alt="Europe">
<area shape="circle" coords="600,150,80" href="asia.html" alt="Asia">
<area shape="poly" coords="100,300,200,280,220,350,120,360" href="africa.html" alt="Africa">
<area shape="default" href="world.html" alt="Rest of world">
</map>
Image maps are not widely used today. Prefer CSS + HTML overlays for interactive image areas.
15. Performance Best Practices
Loading large unoptimised images is one of the biggest causes of slow web pages.
Use the decoding Attribute
<img src="large-photo.jpg" alt="..." decoding="async">
decoding="async" lets the browser decode the image off the main thread, preventing it from blocking page rendering.
Specify an Aspect Ratio in CSS
img {
width: 100%;
height: auto;
aspect-ratio: 16 / 9; /* prevents layout shift even before image loads */
}
Image Optimisation Checklist
[ ] Compress photos before uploading (TinyPNG, Squoosh, ImageOptim)
[ ] Use WebP or AVIF instead of JPEG/PNG where possible
[ ] Set correct width and height attributes to prevent layout shift
[ ] Use loading="lazy" on all below-the-fold images
[ ] Use srcset and sizes to serve correctly sized images at each breakpoint
[ ] Use fetchpriority="high" on the largest image visible on first load (LCP image)
[ ] Never embed text in images — it is not accessible or searchable
[ ] Use SVG for icons and logos that need to scale
16. Accessibility Checklist for Media
Images:
[ ] Every <img> has an alt attribute
[ ] Decorative images have alt=""
[ ] Alt text describes what the image conveys, not just what it contains
[ ] Complex charts and diagrams have a longer description in the page text or aria-describedby
Video:
[ ] All video has captions (<track kind="captions">)
[ ] Important visual content has audio descriptions if not narrated
[ ] Autoplay video is muted or paused
[ ] Users can pause all moving content
Audio:
[ ] Audio has a transcript available on the page or nearby
[ ] Audio does not autoplay
Iframes:
[ ] Every <iframe> has a descriptive title attribute
[ ] Decorative or background iframes have aria-hidden="true"
17. Putting It All Together — A Full Media Section Example
<section aria-labelledby="media-heading">
<h2 id="media-heading">Introduction to HTML5</h2>
<!-- Hero image with responsive sources and lazy loading -->
<picture>
<source
srcset="hero-large.avif 1200w, hero-medium.avif 800w"
type="image/avif"
sizes="(max-width: 600px) 100vw, 800px"
>
<source
srcset="hero-large.webp 1200w, hero-medium.webp 800w"
type="image/webp"
sizes="(max-width: 600px) 100vw, 800px"
>
<img
src="hero-medium.jpg"
alt="A teenager typing code on a laptop, smiling"
width="800"
height="450"
fetchpriority="high"
loading="eager"
>
</picture>
<!-- Video with captions and fallback -->
<figure>
<video
controls
width="800"
height="450"
poster="video-thumbnail.jpg"
preload="metadata"
>
<source src="introduction.webm" type="video/webm">
<source src="introduction.mp4" type="video/mp4">
<track
kind="captions"
src="introduction-captions.vtt"
srclang="en"
label="English captions"
default
>
<p>
Your browser does not support HTML5 video.
<a href="introduction.mp4">Download the video.</a>
</p>
</video>
<figcaption>
Watch the 5-minute introduction to HTML5 on Nandhoo.
</figcaption>
</figure>
<!-- Audio podcast episode -->
<figure>
<audio controls preload="metadata">
<source src="podcast-ep1.ogg" type="audio/ogg">
<source src="podcast-ep1.mp3" type="audio/mpeg">
<p>
Your browser does not support HTML5 audio.
<a href="podcast-ep1.mp3">Download the episode.</a>
</p>
</audio>
<figcaption>Episode 1: Getting started with web development.</figcaption>
</figure>
<!-- Diagram with caption -->
<figure>
<img
src="html-structure.svg"
alt="Diagram showing HTML document structure: html > head and body > various elements"
width="600"
height="400"
loading="lazy"
>
<figcaption>Figure 1: The hierarchical structure of an HTML document.</figcaption>
</figure>
</section>
18. Common Mistakes
| Mistake | Why it matters | Fix |
|---|---|---|
Missing alt attribute | Screen readers announce the filename | Always include alt |
Using alt="image" or alt="photo" | Adds no information | Describe the image content |
Forgetting width and height | Causes layout shift (poor CLS score) | Always set both |
| Uploading 4MB unoptimised photos | Slows page load dramatically | Compress and use WebP |
| No captions on video | Hard of hearing users cannot follow | Add <track kind="captions"> |
| Autoplay video with sound | Startles and frustrates users | Use muted with autoplay |
Omitting title on <iframe> | Screen reader users have no context | Add a descriptive title |
| Embedding text inside images | Not readable by search engines or screen readers | Use HTML text, style with CSS |
| Using GIF for animation | Very large files, poor quality | Use WebP animation or CSS/JS |
19. Mini Exercises
- Create an
<img>tag for a photo of a sunset. Write goodalttext, setwidth="1200"andheight="675", and addloading="lazy". - Wrap the image from exercise 1 in a
<figure>with a<figcaption>describing when the photo was taken. - Create a
<picture>element that serves a WebP version of a hero image on modern browsers, falling back to JPEG on older ones. - Add
srcsetwith three sizes (400w, 800w, 1600w) and appropriatesizesto the<img>fallback. - Create a
<video>element with both MP4 and WebM sources, a poster image, captions track, and native controls. - Create an
<audio>player with MP3 and OGG sources and a link to download the file for browsers without audio support. - Embed a YouTube video using
<iframe>. Add aloading="lazy"attribute and a descriptivetitle.
20. Review Questions
- What happens if you omit the
altattribute from an<img>entirely? - What is the difference between
alt=""andalt="decorative image"? - What does
loading="lazy"do and when should you NOT use it? - How do
srcsetandsizeswork together to serve the right image size? - What is the difference between
<picture>for art direction and<picture>for format switching? - When should you use inline SVG instead of an
<img src="icon.svg">? - What does the
posterattribute on<video>do? - Why should autoplay video almost always include
muted? - What is the
<track>element and what doeskind="captions"mean? - What does
sandboxdo on an<iframe>and why is it important?