
Grouping Media and Code Snippets Semantically with Figure and Figcaption
Many developers only reach for the HTML <figure> and <figcaption> elements when embedding photographs. However, the HTML specification defines <figure> as any self-contained unit of content—with an optional caption—that is referenced from the main flow of the document and could be moved to an appendix or sidebar without breaking the article's meaning.
This makes <figure> and <figcaption> ideal not just for images and charts, but also for captioning <pre><code> snippets and attributing <blockquote cite="..."> quotations in technical documentation.
Example
<!-- Avoid: Disconnected paragraph used as a code filename header -->
<p class="code-title">src/utils/clamp.js</p>
<pre><code>export const clamp = (val, min, max) => Math.min(Math.max(val, min), max);</code></pre>
<!-- Prefer: Semantic figure and figcaption association -->
<figure class="code-figure">
<figcaption>Listing 1 — Clamping a numeric value in <code>src/utils/clamp.js</code></figcaption>
<pre><code>export const clamp = (val, min, max) => Math.min(Math.max(val, min), max);</code></pre>
</figure>
Input : Diagrams, multi-line code listings, and pull quotes inside an article
Output : Semantically grouped <figure> landmarks with programmatic <figcaption> descriptions for screen readers.
Implementation
<!-- 1. Responsive diagram with descriptive caption -->
<figure class="media-figure">
<img
src="/img/dom-event-flow.svg"
alt="Three-phase DOM event flow showing capture phase down to target and bubbling phase back up to window"
width="640"
height="360"
loading="lazy"
/>
<figcaption>
Figure 1 — Standard W3C DOM event propagation through capture, target, and bubble phases.
</figcaption>
</figure>
<!-- 2. Annotated code snippet -->
<figure class="code-figure">
<figcaption id="debounce-caption">
<code>debounce.js</code> — Delaying function execution until user input pauses
</figcaption>
<pre aria-labelledby="debounce-caption"><code>export function debounce(fn, wait = 200) {
let timerId;
return function (...args) {
clearTimeout(timerId);
timerId = setTimeout(() => fn.apply(this, args), wait);
};
}</code></pre>
</figure>
<!-- 3. Pull quote with source attribution -->
<figure class="quote-figure">
<blockquote cite="https://www.w3.org/TR/html52/">
<p>
Authors are encouraged to use the figure element to mark up diagrams,
illustrations, photos, and code examples that are annotated with a caption.
</p>
</blockquote>
<figcaption>
— W3C HTML 5.2 Specification, <cite>4.4.12 The figure element</cite>
</figcaption>
</figure>
.media-figure,
.code-figure,
.quote-figure {
margin: 28px 0;
padding: 16px;
border: 1px solid #e2e8f0;
border-radius: 6px;
background-color: #fafafa;
}
.code-figure figcaption {
font-family: Consolas, Monaco, monospace;
font-size: 14px;
color: #334155;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #e2e8f0;
}
.media-figure figcaption,
.quote-figure figcaption {
margin-top: 10px;
font-size: 14px;
color: #475569;
}
Main Point: Note that <figcaption> is not a replacement for the <img alt="..."> attribute—alt describes the visual contents of the image for users who cannot see it, whereas <figcaption> provides contextual editorial commentary or source attribution for all readers.
Credits
Photo by Andrew Neel