SAE Academy
Images and Media

Figures and Captions

How to associate an image, diagram, or code block with its caption using figure and figcaption.

When you place an image above a paragraph that describes it, there is no connection between them in the HTML. The image is one element. The paragraph is another. The browser, a screen reader, and a search engine all treat them as unrelated.

<figure> and <figcaption> create an explicit relationship between a piece of content and its caption.

The problem with adjacent text

Here is what the broken version looks like:

<!-- No relationship between the image and the caption paragraph -->
<img src="sales-chart.png" alt="Sales chart">
<p>Figure 1: Q1 2024 sales by month. March reached 1,240 units, the highest of the quarter.</p>

From the browser's point of view, this is an image followed by an unrelated paragraph. Three things go wrong:

  • A screen reader reads the alt text, then reads the paragraph as a separate piece of prose. There is no signal that the paragraph is describing the image.
  • If CSS reflows the layout (say, the image floats right), the paragraph might end up visually adjacent to a different image.
  • Search engines cannot infer that the paragraph is a caption.

<figure> and <figcaption>

<figure> is a container for self-contained content. <figcaption> is the caption for that content. Together, they create a machine-readable association.

<figure>
  <img src="sales-chart.png" alt="Bar chart showing Q1 2024 sales by month" width="800" height="500">
  <figcaption>Figure 1: Q1 2024 sales by month. March reached 1,240 units, the highest of the quarter.</figcaption>
</figure>

Screen readers now understand that the caption belongs to the image. The <figcaption> can go before or after the content inside <figure>. Put it after for descriptive captions (the most common case). Put it before when the caption introduces the content -- for example, a title above a diagram.

<!-- Caption after: describes what the figure shows -->
<figure>
  <img src="network-diagram.png" alt="Diagram showing three servers connected to a central load balancer" width="700" height="420">
  <figcaption>The production infrastructure routes all traffic through a central load balancer before reaching the application servers.</figcaption>
</figure>

<!-- Caption before: introduces the figure -->
<figure>
  <figcaption>Figure 3: Memory usage over a 24-hour period.</figcaption>
  <img src="memory-graph.png" alt="Line graph showing memory usage peaking at 87% between 2pm and 4pm" width="700" height="350">
</figure>

The <figcaption> must be a direct child of <figure>

Nesting <figcaption> inside another element inside <figure> breaks the association.

<!-- Wrong: figcaption nested inside a div, association is lost -->
<figure>
  <img src="chart.png" alt="...">
  <div>
    <figcaption>This caption is no longer correctly associated.</figcaption>
  </div>
</figure>

<!-- Correct: figcaption is a direct child of figure -->
<figure>
  <img src="chart.png" alt="...">
  <figcaption>This caption is correctly associated.</figcaption>
</figure>

When to use <figure>

<figure> is for content that is referenced from the main text but could be moved or removed without breaking the flow of the surrounding prose. The classic test: if you can move the content to an appendix and the surrounding text still makes sense, it belongs in a <figure>.

Use <figure> for:

  • An image with a caption
  • A code sample with an explanation
  • A table with a title or description
  • A chart, diagram, or illustration referred to from the prose ("see Figure 2 below")

Do not use <figure> for:

  • A product thumbnail in a shop grid (no caption, no reference from prose)
  • A decorative background or section divider (use CSS, not <img> at all)
  • Every image just to have a container (only wrap in <figure> if there is a meaningful caption or the content is self-contained)

<figure> for code blocks

<figure> works for code samples too. This is useful in documentation or tutorials when you want to label what a code block is demonstrating.

<figure>
  <pre><code>const order = {
  id: 'ord-8821',
  total: 49.95,
  status: 'dispatched'
};</code></pre>
  <figcaption>An order object returned by the API after a successful purchase.</figcaption>
</figure>

<figure> for tables

A table with a caption uses <figure> in the same way:

<figure>
  <figcaption>Table 1: Average monthly rainfall in London (mm)</figcaption>
  <table>
    <thead>
      <tr><th>Jan</th><th>Feb</th><th>Mar</th><th>Apr</th></tr>
    </thead>
    <tbody>
      <tr><td>55</td><td>40</td><td>41</td><td>43</td></tr>
    </tbody>
  </table>
</figure>

Tables have their own <caption> element that goes inside <table>. Both approaches are valid. Using <figure> with <figcaption> is common when you want to style the caption the same way as other figure captions on the page.

Alt text and captions together

The alt attribute and <figcaption> serve different audiences in different ways.

  • alt is read by screen readers when they encounter the <img> element. It is not displayed visually.
  • <figcaption> is visible to all users: sighted users see it, screen readers read it as part of the document.

When the <figcaption> fully describes the image, the alt can be shorter or empty. Duplicating the exact same text in both means screen reader users hear it twice.

<!-- Wrong: identical text in alt and figcaption, screen readers repeat it -->
<figure>
  <img
    src="london-map.png"
    alt="A street map of central London showing the walking route from Paddington Station to Hyde Park, marked in blue."
    width="900"
    height="620"
  >
  <figcaption>A street map of central London showing the walking route from Paddington Station to Hyde Park, marked in blue.</figcaption>
</figure>

<!-- Correct: alt is empty because the figcaption describes the image for everyone -->
<figure>
  <img
    src="london-map.png"
    alt=""
    width="900"
    height="620"
  >
  <figcaption>Walking route from Paddington Station to Hyde Park, central London. The blue line shows the recommended path, approximately 1.2 km, taking 12 minutes on foot.</figcaption>
</figure>

The tradeoff: if the image fails to load, only the alt text displays inline. An empty alt means nothing replaces the broken image. A short, meaningful alt handles the broken-image case while the figcaption handles the descriptive case.

A reasonable approach is a short alt for the broken-image fallback, and a fuller description in the figcaption:

<figure>
  <img
    src="london-map.png"
    alt="Map of central London"
    width="900"
    height="620"
  >
  <figcaption>Walking route from Paddington Station to Hyde Park. The blue line marks the recommended 1.2 km path, approximately 12 minutes on foot.</figcaption>
</figure>

Common mistakes

<figcaption> outside <figure>. The association only works when <figcaption> is inside <figure>. Placed outside, it is just a paragraph.

Using <figure> for every image. If an image has no caption and is not referenced from the text, it does not need <figure>. A <figure> with no <figcaption> is valid HTML, but it signals to browsers and assistive technology that the content is self-contained. Reserve that signal for when it is true.

Writing identical text in alt and <figcaption>. Screen reader users hear the content twice. Write a complementary short description in alt and put the full detail in <figcaption>.

Using a <p> adjacent to an image instead of <figcaption>. A paragraph after an image looks like a caption but carries no semantic association. Use <figure> and <figcaption> when you want a genuine caption.

Putting <figcaption> inside a nested element. <figcaption> must be a direct child of <figure>, not nested inside a <div> or <p> inside the figure.

Exercise

Build a page that uses <figure> correctly in three different situations.

  1. Create a figure with a product image (use https://placehold.co/600x400) and a caption describing a fictional product. Use a short alt for the broken-image fallback and a fuller description in <figcaption>.
  2. Create a figure wrapping a <pre><code> block. The code can be a simple HTML snippet. Write a <figcaption> that explains what the code demonstrates.
  3. Add a standalone image with no <figure> -- a small decorative rule image (https://placehold.co/600x4). Use an empty alt attribute. This shows the contrast between when <figure> is and is not appropriate.

On this page