HTML: Semantic HTML — Figures

HTML Semantic HTML - Figures

Learning outcomes:

  • What is the <figure> element
  • Adding captions using <figcaption>
  • A quick example
  • <figure> vs <img>
  • Things to note regarding <figure> and <figcaption>

What is <figure>?

Often times, when presenting content on a webpage, we come across such discrete and independent units as illustrative images, code snippets, pull quotes, etc. that benefit from a caption.

They don't also necessarily have to be within the reading flow of the webpage — they can as well be displayed separately elsewhere, for e.g. at the bottom of the page, or on some other page.

These units of information are what <figure> is meant for. That is,

The <figure> element represents a self-contained, independent unit of content that benefits from a caption.

For instance, let's say you have a technical blog post on JavaScript and there is a diagram to explain the event loop's architecture.

A diagram visualizing the working of the event loop in JavaScript
A diagram visualizing the working of the event loop in JavaScript

This diagram is a self-contained, illustrative image meant to better explain the underlying concept of an event loop, plus it also benefits from having a caption like "Diagram explaining how the event loop works."

Hence, it's ideal for <figure>.

It's important to note that, by definition, a <figure> must be referenced in one way or the other but it must NOT be tightly coupled to the reading flow of the content (we'll learn more about this later in this chapter).

Here's what the HTML standard states about the <figure> element:

The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.

As another example, consider the same technical post that we talked about above, this time containing a code snippet (marked up using the <pre> and <code> elements).

Each code snippet is numbered in the article, e.g. 'Code listing 1.1', and it's meant to contain a small descriptive text stating its purpose.

Marking up this code snippet with <figure> is a great idea. "Why?" you ask. Simply because it's self-contained and captioning it makes sense.

Always try using HTML to its full potential by leveraging the most appropriate element for the task at hand.

Now since <figure> typically annotates content that helps to have a caption, there is a related element to explore — <figcaption>.

What is <figcaption>?

The <figcaption> element serves a very simple purpose — to caption a <figure>.

The <figcaption> element is used to specify the caption text for a <figure> element.

As expected, <figcaption> can only be nested inside <figure> and it can appear only once inside of it. We'll reiterate on these important points later below.

The <figcaption> element can contain such elements in it as <p>; <h1>, <h2>, and the rest of the heading elements; <blockquote>, etc.

Keep in mind that it isn't necessary to have a <figcaption> in every single <figure> but it's often the case.

A quick example

Let's consider a concrete example of using <figure> and <figcaption> to denote a figure in HTML. We'll go with the familiar, hypothetical, event loop diagram we talked about above.

In the following code, we first mark up the image using <img> and place it inside <figure>:

HTML
<figure>
   <img src="event-loop-diagram.png" alt="A diagram visualizing the event loop in JavaScript">
</figure>
For an in-depth discussion on how to use the <img> element in HTML, refer to HTML Images — Basics.

And then, we give it a nice caption text, leveraging the <figcaption> element:

HTML
<figure>
   <img src="event-loop-diagram.png" alt="A diagram visualizing the event loop in JavaScript">
   <figcaption>Figure 1: A diagram visualizing the event loop in JavaScript</figcaption>
</figure>

Notice how the text inside the <img>'s alt attribute and the <figcaption> element is the exact. This isn't a necessity, per se, but there isn't any issue in doing so.

Adding a labeling phrase inside <figcaption>, like 'Figure 1' in the code above, isn't a requirement. However, I feel it's good to do so when we need to refer to the figure explicitly.

Let's see the result of this simple HTML:

Live Example

As you can see, there is some space around the entire figure. This comes from the default styling applied to <figure> by default in HTML whereby it gets the application of margins around it.

As for the <figcaption> element, there isn't anything interesting about it; it's just a block-level element without any styling.

One worthwhile point mentioning here is that if we want to, we can wrap up the caption text that's inside <figcaption> within a <p>:

HTML
<figure>
   <img src="event-loop-diagram.png" alt="A diagram visualizing the event loop in JavaScript">
   <figcaption>
<p>Figure 1: A diagram visualizing the event loop in JavaScript</p>
</figcaption> </figure>

I personally prefer to directly place the text inside <figcaption> but you can choose whatever you wish to. Regardless, it's imperative to stay consistent with what you choose.

<figure> vs. <img>

You might have the following questions in your mind at this point:

What's the point anyway of having <figure> define the caption for an image?

Why can't we just have the caption for an image in a <p> or maybe a <div> right after the <img>?

Well, the benefit of using <figure>, thanks to <figcaption>, is that we get to present descriptive text both visually and for screen readers.

Talking about the <img> element, as we know, we have the alt attribute to present this descriptive text but there are many limitations to it:

  • alt can only be specified on <img>. For example, a code snippet can NOT semantically be captioned using it.
  • alt only shows visually when the image doesn't load, which doesn't look nice at all from a design perspective.
  • alt can't contain HTML markup in it because... well... it's just an attribute that's meant to contain flat text.

Putting these limitations of alt in front of us, it's a no-brainer to deduce that <figure> and, with it, the <figcaption> element make for a superior combination to mark up (self-contained) images in an HTML document along with captions.

Things to note

<figure> can be nested inside <figure>

The official HTML standard has a great example to help explain this idea of <figure> nested inside <figure>. I present it in my own way below.

Say we have a group of images of a new interior of a room. There are multiple pictures from different angles of the same room. This entire group of images is referred to as 'Figure 1' in an analysis post (an online HTML document) of the interior.

Hence, first things first, the entire group is a perfect candidate for <figure> because the entire group is a self-contained media unit, with a sensible caption.

Moving on, each individual image of the room in this group is also ideal for <figure> because it's self-contained too and can as well exist on its own. The first figure is called 'Figure 1.1', the second one is called 'Figure 1.2', and so on.

Each of these <figure>s can also have an associated <figcaption> to describe the underlying figure's content.

All in all, it's possible — and in fact, practical (as this example demonstrates) — to have <figure> nested inside <figure>.

<figure> isn't only for images

It's quite common to wrongly assume that <figure> is only meant to contain images. While it certainly might be that images are the most common type of content annotated by <figure>, by no means are they the only one.

As stated earlier, <figure> could represent images, code snippets, pull quotes — basically anything that stands on its own and would benefit from having a caption.

Shown below is an example:

HTML
<figure>
   <pre><code class="lang-javascipt">console.log('Hello World');</code></pre>
   <figcaption>A simple, greeting, JavaScript program</figcaption>
</figure>

The <figure> here is used to represent a code snippet, along with a caption that explains the purpose of the code snippet.

<figure> must be independent and self-contained

Consider the following code:

HTML
<p>If the box you bought looks something like this:</p>

<figure>
   <img alt="A white colored paint box" src="/assets/boxes/1.jpg">
</figure>

<p>then you've bought the right thing!</p>

The <figure> shown is tightly sewn into the content around it; removing it would clearly affect the meaning of the content since the sentence completes only with the image.

This is a perfect example of where <figure> is NOT appropriate.

If an image is tightly coupled to content such that it's impossible to extract it out from the content, then it's recommended to avoid the <figure> element — just put the image as it is.

Likewise, a better version of the HTML above would be either to remove the <figure> completely and just use an <img> as is, as follows:

HTML
<p>If the box you bought looks something like this:</p>

<div>
   <img alt="A white colored paint box" src="/assets/boxes/1.jpg">
</div>

<p>then you've bought the right thing!</p>

or either use a <figure> but then change the prose of the sentence so that it would make sense even when the figure it located elsewhere:

HTML
<p>If the box you bought looks something like the one shown in Figure 1 then you've bought the right thing!:</p>

<figure>
   <img alt="A white colored paint box" src="/assets/boxes/1.jpg">
   <figcaption>Figure 1: A white colored paint box</figcaption>
</figure>

<figcaption> can only go inside <figcaption>

Needless to say it, but still worth reiterating, the <figcaption> element can only go inside a <figure>. And it must be a child of <figure>.

Likewise, the following is invalid HTML since <figcaption> is nested inside a <div> which is a child of the <figure>.

HTML
<figure>
   <img src="some-image.jpg" alt="Some alternative text">
   <div>
      <!-- The <figcaption> element MUST be a child of <figure>! -->
<figcaption>This is some caption</figcaption>
</div> </figure>

The correct markup is as follows, taking the <figcaption> out:

HTML
<figure>
   <img src="some-image.jpg" alt="Some alternative text">
<figcaption> <div>This is some caption</div> </figcaption>
</figure>

A <figure> can have at most one <figcaption>

This point also makes perfect sense. That is, a <figure> can have at most one <figcaption>.

You tell me. Does it make sense for a <figure> to have two captions? No right. Likewise, it's invalid to have more than one <figcaption> inside <figure>.

In this way, the following HTML is invalid:

HTML
<figure>
   <img src="some-image.jpg" alt="Some alternative text">

   <figcaption>This is caption 1</figcaption>

   <!-- Can't have more than one caption! -->
   <figcaption>This is caption 2</figcaption>
</figure>

If <figcaption> exists, there's no need for alt

When denoting images using <figure>, it's common to use <figcaption> to caption those images. In this case, it's extremely important to note that you must refrain from adding alt text in those images.

HTML
<figure>
   <!-- No need for `alt` here! -->
   <img src="some-image.jpg" alt="Some alternative text">
   <figcaption>This is some caption</figcaption>
</figure>

The reason for this is because assistive technology typically reads the content of <figcaption> associated with a <figure> right when focus moves into the <figure>.

Likewise, having an image with alt would meant that such technology double reads the caption, this time for the alt attribute of <img>. And as you can reason, this isn't really nice.

What we should do in this respect is to include the alt attribute (remember, all <img> element must have alt on them) but keep it empty.

Something as follows:

HTML
<figure>
   <!-- `alt` is empty here by virtue of having a caption below -->
   <img src="some-image.jpg" alt="">
   <figcaption>This is some caption</figcaption>
</figure>

In this HTML markup, notice how the value of alt is empty, i.e. "". This is because the underlying <img> is already within a <figure> that is captioned.

So when a screen reader comes inside the figure, there is no chance of double-reading the caption. In the event where the screen reader enters the image, nothing is read because... well... there just isn't anything to read.

Small details matter in HTML!

Do keep in mind that having alt on an <img> that is inside a <figure> with a <figcaption> is NOT invalid HTML; it's perfectly valid! It's just that it's not good for accessibility technology users, who will get the captions read out twice — once for the <figcaption> and once for the alt attribute.

Spread the word

Think that the content was awesome? Share it with your friends!

Join the community

Can't understand something related to the content? Get help from the community.

Open Discord

 Go to home Explore more courses