Figures, pictures, and art direction
Beyond dropping an <img> on the page with a basic srcset. We cover <figure> and <figcaption> for meaningful images, then <picture> for art direction – serving a different crop or composition at different breakpoints, not just a smaller file.
<figure> and <figcaption>
A <figure> wraps self-contained content that the main document could reference – a photo, diagram, chart, or code snippet. The optional <figcaption> gives it a caption. Use these when the image (or other media) is part of the content, not just decoration.
<figure>
<img src="workshop-room.jpg" alt="The Codeskill workshop room with desks and monitors">
<figcaption>Our Manchester classroom - bring your own laptop.</figcaption>
</figure>
Do not use <figure> for every image on a page. Hero banners, background textures, and icons beside menu items usually stay as plain <img> elements (or CSS backgrounds) without a figure wrapper.
alt and <figcaption> do different jobs. alt describes the image for people who cannot see it. The figcaption adds context – a title, credit line, or explanation. They can overlap slightly, but the figcaption should not simply repeat the alt text word for word.
Responsive images recap
The beginner tutorials introduced srcset and sizes so the browser can pick an appropriately sized file. Quick reminder:
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1000px) 50vw, 800px"
alt="Students working on laptops in a bright classroom"
width="800"
height="450">
srcsetlists available files and their widths (400wmeans 400 CSS pixels wide).sizestells the browser how wide the image will be on screen at different viewport widths.widthandheighton the<img>reserve space and reduce layout shift while the file loads.
That pattern saves bandwidth. Art direction is a different problem: sometimes you want a different crop, not just a smaller version of the same shot.
Art direction with <picture>
Imagine a wide group photo used as a page banner. On a phone, you might prefer a tighter crop on the speaker rather than scaling the whole panorama down to illegibility. <picture> lets you offer different sources for different conditions.
<picture>
<source media="(min-width: 900px)" srcset="speaker-wide.jpg">
<source media="(min-width: 600px)" srcset="speaker-medium.jpg">
<img src="speaker-close.jpg" alt="Dan Slade speaking at a web development workshop">
</picture>
The browser evaluates each <source> in order and uses the first one whose media query matches. The final <img> is required – it is the fallback and carries the alt text.
Combining format choice and art direction
<source> can also list modern formats. Browsers that support WebP or AVIF get a smaller file; others fall back to JPEG:
<picture>
<source type="image/avif" srcset="course-hero.avif">
<source type="image/webp" srcset="course-hero.webp">
<img src="course-hero.jpg" alt="Screenshot of the Codeskill HTML course homepage">
</picture>
You can combine type, media, and srcset on separate sources when you need both format negotiation and breakpoint-specific crops. Keep the markup readable – three or four sources is common; fifteen is a maintenance headache.
Putting it together in a figure
<figure>
<picture>
<source media="(min-width: 768px)" srcset="chart-desktop.png">
<source media="(min-width: 768px)" type="image/webp" srcset="chart-desktop.webp">
<img
src="chart-mobile.png"
srcset="chart-mobile.png 360w, chart-desktop.png 720w"
sizes="(min-width: 768px) 600px, 100vw"
alt="Bar chart showing course completion rates by month"
width="360"
height="240"
loading="lazy">
</picture>
<figcaption>Completion rates rose after we added weekly check-ins.</figcaption>
</figure>
Loading and performance attributes
A few attributes worth knowing at this level:
loading="lazy"– defer loading images below the fold until the user scrolls near them.loading="eager"– load immediately (default). Use for hero images and anything above the fold.decoding="async"– decode the image off the main thread where supported.fetchpriority="high"– hint that this image matters for the first paint (sparingly, usually one per page).
Lazy-loading everything including your largest hero image is a common mistake. If the user sees it immediately, do not lazy-load it.
Decorative images
Pure decoration – a repeating pattern, a flourish beside a heading – should not clutter screen reader output. Use an empty alt attribute:
<img src="divider.svg" alt="" role="presentation">
If removing the image would lose information, it is not decorative – write a proper alt.
Checklist before you ship
- Does this image need a figure and caption, or is a plain
<img>enough? - Is
alttext accurate and concise? - Do you need art direction (
<picture>withmedia) or just resolution switching (srcset+sizes)? - Are
widthandheightset to match the displayed aspect ratio? - Have you checked the result on a narrow phone and a wide monitor?
Responsive images are not one attribute and done. They are a set of tools – figure semantics, format fallbacks, size hints, and deliberate crops – chosen to match what the page actually needs.

