Having figure match width of contained image

Posted 5 days ago

On Monday, I was working on a layout where the client wanted an image centered in the page. I also had another use case where the image would be floated to let the other content beneath flow around the image. The image also had a caption. I knew that I wanted to put the image within a figure element and use figcaption for the caption.

<figure>
  <img src="foo.jpg" alt="" />
  <figcaption>A caption for my image</figcaption>
</figure>

I wanted a way to make the figure had the same width as the image and have the figcaption wrap if it had a longer width than the image. I could not use a width: max-content on the figure because it would take on the width of the figcaption. Or if the text was long enough to need 2 lines to wrap inside the larger content container, putting a width: min-content on the figure without also putting a max-width: 100% would cause the figcaption and figure to overflow the content container.

See the Pen figcaption overflow by Jeff Bridgforth (@webcraftsman) on CodePen.

Overflow contained

See the Pen figcaption overflow by Jeff Bridgforth (@webcraftsman) on CodePen.

I decided to try to look up a solution. Because AI is now built into the browser, it gave me a possible solution and I was curious to see if it actually worked. The solution applied display: table to the figure and display: table-caption and caption-side: bottom to the figcaption. I tried it out and it did work. The figure takes on the width of the image and centers image and figcaption.

figure {
  display: table;
  margin-block: 0;
  margin-inline: auto;
}

img {
  height: auto;
  max-width: 100%;
}

figcaption {
  display: table-caption;
  caption-side: bottom;
  margin-block-start: .5em;
}

See the Pen figcaption overflow by Jeff Bridgforth (@webcraftsman) on CodePen.

But I wanted to see if others had solved the problem. So I asked a couple of CSS wizards on Bluesky. My initial post set off a chain of responses by many people who I did not mention in my original post.

Jeff Bridgforth

@jeffbridgforth.com

Has anyone come up with a trick to make the width of a figure element fit the content of contained image even when figcaption has more width? I want figcaption to wrap. @kevinpowell.co @bell.bz @ishadeed.com @michelleb.bsky.social @chriscoyier.net @5t3ph.bsky.social

The first response I got was from Chris Coyier:

Chris Coyier

@chriscoyier.net

I’ve had that come up before but have super dug into it. it’s like you want a parent element to be the `max-content` one child element but not the other. It’s gotta be doable. Make a (broken) reduced test case.

Kevin Powell

@kevinpowell.co

I think a `width: min-content` would work, as long as the image doesn’t have `max-width: 100%` on it. Of course, we usually want that, but depending on how/where the figures are being used, it’s possible it’s not required?

Chris Coyier

@chriscoyier.net

Reduced test case for what Kevin is saying… https://codepen.io/chriscoyier/pen/NPqyKVz/ if you can skip the max-width it works great, otherwise another solution is needed.

See the Pen figure/figcaption issue by Chris Coyier (@chriscoyier) on CodePen.

Nils Binder responded to Chris simple use case.

Nils Binder

@ichimnetz.com?

https://codepen.io/enbee81/pen/zxGRYZv?editors=1100
Switching to Flex should do it as well

See the Pen figure/figcaption issue by Nils Binder (@enbee81) on CodePen.

figure {
  /* this *should* do it */
  display: flex;
  flex-direction: column;
  max-width: min-content;
}

Ana Tudor also chimed in:

Ana Tudor

@anatudor.bsky.social?

This is what I’ve used before. Also: to fix the image max width problem and prevent overflow, the figure wrapper (whose size doesn’t depend on the figure) can be made a container https://codepen.io/thebabydino/pen/GgJybmx

See the Pen Untitled by Ana Tudor (@thebabydino) on CodePen.

CSS by T. Afif

@css-only.dev?

or my favorite `min-width: 100%;with: 0` trick
https://stackoverflow.com/a/55041133/8620333

From his Stackoverflow:

Make the container inline-block (or any shrink-to-fit configuration like table,inline-grid,inline-flexfloat,absolute etc) then force the width of text to be 0 so the width of the container is defined by the image (the text doesn’t contribute to the width) then force the width again to be 100% using min-width

…We can also use contain: inline-size that will do the same job as width:0; min-width:100%;

CSS by T. Afif

@css-only.dev?

And as I mention in my answer, “contain: inline-size” is also a good solution. The one I would probably recommend in 2025. I don’t know why I never shared this as a CSS tip. I only did with the vertical version that relies on the same trick: https://css-tip.com/equal-height-column/

CSS by T. Afif

@css-only.dev

See the Pen figure/figcaption issue by Temani Afif (@t_afif) on CodePen.

figure {
  display: inline-block; /* shrink to fit element */
}
figcaption {
  contain: inline-size; /* no size contribution for figcaption */
}
img {
  max-width: 100%; /* you can have max-width */
}

Then Stephanie Eckels replied to T. Arif:

Stephanie Eckles

@5t3ph.bsky.social?

Ooh, super clever use of containment! Here’s a little swap from `display: inline-block` to using `inline-size: fit-content` so we can center with auto margins https://codepen.io/5t3ph/pen/JodpOOR

See the Pen figure/figcaption issue by Stephanie Eckles (@5t3ph) on CodePen.

figure {
  /* original - shrink to fit element */
  /* display: inline-block;  */
  
/*   Update - Swap to fit-content to retain margin access */
  inline-size: fit-content;
  margin-inline: auto;
}
figcaption {
  /* no size contribution for figcaption */
  contain: inline-size;
}
img {
  /* you can have max-width */
  max-width: 100%; 
}

As you can see, there are many different ways to solve this problem. They all work. And as Andy Bell reminded me recently, If it works, it’s right.

I think if I had to pick the solution that I favor the most, it would be Stephanie’s solution. It uses a logical property, inline-size, instead of width. It uses the clever contain, which I have never used before. And it is very simple. It does not require changing the display property and is very straightforward.

See the Pen figcaption overflow by Jeff Bridgforth (@webcraftsman) on CodePen.

And with the figure floating to wrap other content:

See the Pen Match figure to image width and wrap figcaption by Jeff Bridgforth (@webcraftsman) on CodePen.

Comment on this post