The foundational structure
Semantic HTML 2: Images and Media
Introduction
A picture might be worth a thousand words, but in web design it’s worth a whole lot more than that — done well, it improves accessibility, boosts performance, and gives users a better experience regardless of their device or connection speed.
In this module, you’ll learn how to add images to a webpage properly, not just by dropping them in. You’ll look at four HTML elements used for images, the attributes that make those images accessible and performant, and how to use Builderius to build all of it hands-on.
What you’ll be able to do after this module
By the end of this lesson, you’ll be able to:
- explain the difference between
<img>,<figure>,<figcaption>, and<picture>, and know when to use each one - add an image in Builderius with the correct attributes for accessibility and performance
- write useful alt text — or know when to leave it intentionally empty
- use
srcsetandsizesto give the browser a choice of image files based on screen size - use the
<picture>element to serve different images at different breakpoints or in different formats
The four elements you need to know
Think of a framed graduation photograph. That single image captures what all four elements do together.
| Element | What it represents |
|---|---|
<img> |
The photograph itself |
<figure> |
The frame around it |
<figcaption> |
The description written underneath |
<picture> |
Multiple versions of the same photo — different crops for different sizes |
The <img> element and its attributes
An image element on its own does nothing. You need attributes to tell the browser where to find the image, what it shows, and how to load it.
Source (src)
This is the URL of the image file. In Builderius, you select an image directly from your WordPress media library, which pulls in the URL automatically. If you’ve filled in the image details in the media library, it’ll also pull in the alt text.
Alt text (alt)
Alt text is what screen readers announce in place of the image. It is also displayed if the image fails to load.
Deciding what to write can feel tricky. The W3C publishes an Alt Decision Tree that walks you through a set of questions to help you work out what your alt text should say. That’s worth bookmarking.
If you’re stuck on where to start, you can use an AI tool like Claude or Gemini to generate a first draft — paste in the image and ask for a description — then rewrite it in your own words to suit the context of the page.
Two things to remember:
- Always include the
altattribute on every<img>element. - If the image is decorative (it adds no meaning to the page), leave the attribute value empty:
alt="". Do not remove the attribute entirely — that’s different, and it’s worse for screen reader users.
Loading (loading)
The loading attribute controls when the browser fetches the image. There are three values:
lazy— the browser waits to load the image until it’s near the user’s viewport. Use this for images below the fold.eager— the browser loads the image immediately, regardless of position. Use this for hero images and logos.auto— leaves the decision to the browser.
Width and height
Defining the pixel dimensions of your image as HTML attributes prevents cumulative layout shift (CLS) — the visible jumping around that happens when images load and push other content out of the way.
Browsers load HTML before CSS. Without width and height attributes, the browser doesn’t know how much space to reserve for the image until the CSS arrives. With them, it can reserve the right amount of space straight away.
Important: when setting these as HTML attributes (not CSS), you write the number only — no px unit. So width="800" not width="800px".
Giving the browser a choice: srcset and sizes
If you want to go further — and you should for most images — you can provide a set of alternative image files and let the browser pick the most appropriate one for the user’s screen and connection.
These two attributes work together.
srcset
srcset is a list of image files, each paired with its width in pixels using the w unit descriptor. Example:
html
srcset="image-800.jpg 800w, image-300.jpg 300w"
You’re not choosing the image — you’re offering options. The browser decides.
sizes
sizes tells the browser how much of the screen the image will take up at different breakpoints. This gives the browser the context it needs to pick the right file from the srcset.
Example:
html
sizes="(max-width: 768px) 100vw, 50vw"
This tells the browser: on screens up to 768px wide, the image fills the full viewport width. On larger screens, it takes up about half.
These are estimates — they don’t have to be exact. The goal is to give the browser useful information so it can serve an appropriately sized image, rather than always loading the largest one.
In Builderius, you add srcset and sizes as custom attributes in the attributes panel. Everything set in the primary panel is also visible there, and the two stay in sync — so if you delete an attribute from one place, it’s gone from both.
The <figure> element
<figure> is a wrapper for self-contained content — typically an image with an optional caption. It’s the semantic equivalent of the frame around a photograph.
The key question is: could this image be moved elsewhere in the document (say, to an appendix or sidebar) without disrupting the meaning of the surrounding text? If yes, <figure> is appropriate.
If the image is directly embedded within a sentence — for example, a logo that’s part of a navigation link — then <figure> is not the right choice.
In Builderius, you change the HTML tag on a wrapper <div> to <figure> to make this switch. It’s a small change, but it’s meaningful for screen readers and for the document’s semantic structure.
The <figcaption> element
<figcaption> provides a visible caption for the figure. It must be either the first or last child element inside <figure>. It cannot sit in the middle.
In Builderius, you add a figcaption element into the figure wrapper and add your caption text in the primary content area.
The <picture> element
<picture> lets you define completely different image files for different scenarios — not just different sizes of the same image, but different crops, different formats, or images that change based on breakpoint.
It wraps your <img> element and sits inside your <figure> (not the other way around — <picture> is directly related to the image, not to the figure wrapper).
Inside <picture>, you define one or more <source> elements before the <img>. Each <source> can have:
srcset— the URL of the image to usemedia— a media query that determines when this source appliestype— the image format (e.g.type="image/avif")sizes,width,height— as with the<img>element
The <img> at the end acts as a fallback. If none of the <source> conditions match — or if the browser doesn’t support <picture> — the <img> is what gets shown.
A practical use case: you might define an AVIF version of an image for browsers that support it, and a WebP fallback for those that don’t. Or you might swap in a portrait-cropped image on mobile and a landscape version on desktop.
Resources mentioned in this module
- W3C Alt Decision Tree — a practical guide to writing alt text
- MDN:
<img>element — full attribute reference - MDN:
<picture>element — full reference including<source>attributes - Builderius pricing — if you’re ready to get started with the builder used in this course
What’s next
In the next module, you’ll look at another set of semantic HTML elements — this time focused on lists. See you there.