There is a problem with the default styling of the figure caption (figcaption) element that is intrinsic to the way HTML and CSS work on their simplest level. Elements don’t know or care about the other elements around them; they behave in their own way, no matter what content comes before or after them. Let’s take a look at why the figcaption throws a wrench into this idea.
figure { display: table; } figcaption { display: table-caption; caption-side: bottom; /* optional */ }
Off to a good start
We’ll begin with a fairly unassuming article layout. It has an image floated to one side and content flowing around it.
Note: the direction of the float (left or right) is not a factor in the forthcoming issue.
See the Pen Figure with Caption #1 by Zach Handing (@zachhanding) on CodePen.
This layout as it stands works exactly as we want it to. We haven’t set a width or height on the floated image, because we want the ability to put in an image of any size as it relates to our article. We set margins on the side and bottom so that the content doesn’t crowd our image, and we add max-width: 100%;
to ensure that if we drop in an image that is a larger resolution than our page affords, it won’t break the layout.
Running into our image caption problem
Now we want to add a caption to our image. In the world of semantic HTML, this is a straightforward process. All we need to do is put a figcaption directly after our image, and wrap both elements in a figure. We can take the margin and float rules off the image directly and put them on the figure since we’ll want these rules to apply to the image and caption as a whole.
With a short caption all appears fine, but as soon as we write a caption that takes up more width than our image, our layout breaks.
See the Pen Figure with Caption #2 by Zach Handing (@zachhanding) on CodePen.
This is happening because the caption doesn’t know how wide the image is, and it doesn’t care. It knows how much space it needs, and it knows there’s enough room for it, so it takes up all the room needs. It has no reason to know we want it to start wrapping to a new line once it reaches the width limits of the image.
Brainstorming image caption solutions
The cop-out
Now, one way to solve this issue is to let the caption know exactly how wide we want it to be. We can set an explicit width on the figure so that the image and caption are always the same size, but that’s not what we’re going for here. We want to put in any size image, and have the caption adapt and align to it.
Thinking outside the block
Enter display: table-caption;
HTML tables are very interesting little creatures, even though they have a pretty bad rap nowadays. One thing tables do extremely well is automatically handling the widths of the elements inside them. A table will figure out the size of each column for you. That goes for the caption of a table as well. A table will make itself as wide as its contents need, and it applies the same width to any caption inside it. Luckily for us, this behavior has been adopted into CSS, and we can apply it to any element using the display: table;
and display: table-caption;
rules. Let’s take another look at our solution.
figure { display: table; } figcaption { display: table-caption; caption-side: bottom; /* optional */ }
Instead of displaying the figure as a block element, we tell it to display as a table instead. And likewise with our figcaption, we tell it to display as a table-caption. Now our figure looks at all the content inside of it (except the figcaption) and makes itself as wide as it needs to be. In this case, the figure simply takes on the width of the image. It then takes that width and ensures the figcaption adheres to it as well. This then makes our caption wrap to multiple lines once it reaches the limits of the image.
See the Pen Figure with Caption Final by Zach Handing (@zachhanding) on CodePen.
One more thing…
The last piece to this particular puzzle is to put the caption back below the image where we wanted it. By default, the table-caption style puts the caption at the top of the table. This is reversed by declaring caption-side: bottom;
. This is of course optional, as you can keep your caption above the image if you so choose.
Image captions: now solved with CSS.
If you liked this, check out my previous post about using Sass mixins to create the Teenage Mutant Ninja Turtles.