There is this problem with this, when it comes to layout:
<figure>
<img src="image.jpg" alt="good description of image" />
<figcaption>This is a pretty long caption that I want for the image. It's such a long bit of text that it's likely going to wrap in the layout.</figcaption>
</figure>
Code language: HTML, XML (xml)
The problem isn’t with the HTML, that’s fine.
The problem is when the image is less wide than the container and we want the figcaption to only be as wide as the image is.
We want this:

We want that orange buddy. That’s the <figure>
element sitting in the middle of this article, centered, with an <img>
inside that isn’t the full width of the article, and a <figcaption>
inside that wraps at the edges of the image.
How hard can that be?!
Well — it certainly is weird.
This all started with a post from Jeff Bridgforth that piqued my interest:
See, I’d run into this myself. On my own blog, I often post photos that are not the full width of the page and want to center them or float them to a side or something. And the thing that limits the width of the <figcaption>
is the parent <figure>
itself, not the <img>
. So how do you limit the <figcaption>
width?
On my own blog, I was just like screw it and set a max-inline-size
on them.

figcaption { max-inline-size: 300px; }
For the most part I chalked it up as a design decision that had kind of a cool look. But it still bugged me. Like the image above where the figcaption still ends up wider than the image.
There is a proper solution here.
Jeff was smart enough to blog the entire conversation and solutions that came out of his post. And frankly he did a good job and this blog post probably isn’t entirely necessary. But hey if it helps more people when they run into this, that’s cool.
Allow me to jump straight to the end and showcase the best solution, by Stephanie Eckles:
There it is, the perfect solution here.
figure {
inline-size: fit-content;
margin-inline: auto;
}
figcaption {
contain: inline-size;
}
/* Probably in your reset stylesheet, which is good. */
img {
max-width: 100%;
}
Code language: CSS (css)
min-content
the <figure>
?
Wouldn’t you think you could just Like:
figure {
inline-size: min-content;
}
Code language: CSS (css)
That’s what my brain does and I heard from others the same. The image would be the smallest content within the figure (otherwise it would be just a word), so the figure should kinda shrink-wrap around the image.
The thing is… you can and it works… unless… you use the classic reset stylesheet thing:
img {
max-width: 100%;
}
Code language: CSS (css)
I’m a fan of this. It’s protection against a too-wide image busting out of a container. It’s a classic, and it’s important. This is more like reality, where width
and height
attributes are on the image, because that’s a best-practice for maintaining aspect ratio space as the image is loading.
<img src="..." alt="..." width="4000" height="2000" />
Code language: HTML, XML (xml)
img {
/* prevent blowouts */
max-width: 100%;
/* maintain aspect ratio */
height: auto;
/* opinionated, but removes line-height space below block images */
display: block;
}
Code language: CSS (css)
But if we do this, we’re essentially wiping away the intinstic size of the image and the min-content
width becomes based on the figcaption
instead and we get smashy-smashy thin time:

What’s with mixing logical properties like inline-size
in some places and non-logical properties like max-width
in others? I’m a fan of almost always using logical properties, but for most images, even changing to a vertical writing mode shouldn’t rotate images, so properties like width
make sense.
The Best Tricks Are About Using The Images Intrinsic Size Instead Of The Figcaption
The core of the trick is:
figcaption {
contain: inline-size;
}
Code language: CSS (css)
That says: don’t factor in the figcaption in determining the intrinsic inline-size of the parent.
There was a way to do this before, as Temani Afif pointed out, with weirder trickery:
figcaption {
inline-size: 0; /* or width */
min-inline-size: 100%; */ or min-width */
}
Code language: JavaScript (javascript)
Combined Demos
Video
While I was wrapping my mind around all this, I popped on a stream to do it. This isn’t like a straightforward tutorial, it’s the exploratory poking around and trying stuff that lead to my own better understanding (and the demos and this blog post).
Very cool, tried it without the
margin-inline: auto;
and it works fine too.Chris, thanks so much for your kind words. I think this post is entirely necessary because you have taken the time to understand the solution, learn new techniques, and add more to the conversation.
I am amazed to see how my simple question has evolved into various approaches to solving it, and people learning new things along the way. Thanks for adding more to the conversation. I hope that all of this encourages others to ask questions out loud and for lots of people to “listen in” and learn together.
The Universe sometimes is a weird thing! You ask it for help, and then you get an answer.
The day before yesterday I had the same exact issue, solved it with
display: inline-flex
andflex-direction: column
, but saw the potential drawbacks of an inline element.And the yesterday I stumbled upon your video/stream and was amazed by the simplicity and beauty of Stephanie‘s solution. This came at the right time.
Just a thought that I didn’t articulate well in the article:
The goal here is sizing a parent element based on the size of a child element — but getting to choose which child element.