28

I am essentially trying to create a version of the "figure" element (upcoming in HTML5), whereby I have an image with a short description below it.

However, I want to limit the width of this entire element to that of the image, so the text isn't wider than the image (wrapping to multiple lines if necessary).

Basic HTML:

<div class="figure">
<img src="..." alt="..." width="..." height="..." /><br />
A description for the image
</div>

I'm well-versed with CSS but I can't think of any pure CSS solution, without adding a style="width:100px" to the div to match the image width.

Update: After a bit of searching and thinking, the best method seems to be using an inline width on the div. I will keep the width attribute on the image, in case I wish the div to be a bit wider than the image (for example to accomodate a longer caption).

This approach also means I could have two images side-by-side with a caption below. If I have a set of images the same size, I can of course add an extra style to each div.

Thanks to everyone who answered!

DisgruntledGoat
  • 70,219
  • 68
  • 205
  • 290
  • What's wrong with setting the width on the div? – strager Mar 06 '09 at 02:15
  • I just don't think it's good code. For starters it means I'm duplicating the width declaration. If I change the image width I must change the div width too. (I know they're only next to each other.) There is a solution below though. – DisgruntledGoat Mar 06 '09 at 15:00

6 Answers6

23

This could also be accomplished using 'display: table-caption' for the caption, as follows:

HTML

<div class="wrapper">
  <img src="image.jpg" />
  <div class="caption">My caption...</div>
</div>

Stylesheet

.wrapper {
  display: table;
}

.caption {
  display: table-caption;
  caption-side: bottom;
}

This block can also be floated left of right of other text. I've tested this in IE8+. Here's a JSBin example: http://jsbin.com/xiyevovelixu/1

Hedley Smith
  • 1,307
  • 15
  • 12
  • This solution will only work as long as you don't need any borders or background at `.wrapper`, since both will collapse to the image only. This is consistent in Chrome, FF & Edge – Möhre Jun 08 '16 at 09:12
9

For setting the width to match the image automatically you could use

.figure {
  display: table;
  width: 1px;
}

This makes the div behave like a table (not supported in Internet Explorer). Or you could use a table instead of the div. I don't think there is another way of setting the width automatically.

Edit: The simplest way is to forget about the auto width and set it by hand. If it is really needed you can use JavaScript or a table. In this case the use of a table is not so ugly because you are addressing a limitation of the HTML version. In the case of server-side scripting you could also set the width when generating the page.

Angel
  • 401
  • 1
  • 4
  • 11
  • Your example by setting the display doesn't work in IE7. Not sure about IE6. – strager Mar 06 '09 at 02:17
  • According to http://www.quirksmode.org/css/display.html it's not supported by released versions of IE. I guess the only option then is to use a table. – Angel Mar 06 '09 at 02:29
3

Stylesheet

div.figure img,
div.figure div.caption {
    width: 100%;
}
div.figure div {
    overflow: hidden;
    white-space: nowrap;
}

note: to enable wrapping just remove that last css line

HTML

<div class="figure" style="width:150px;">
    <img src="logo.png" alt="logo" />
    <div class="caption">A description for the image</div>
</div>

I've checked it in Chrome, Firefox and IE7 and it looks good in all three. I realise this has the width on the div and not the img, but at least you only need to set the width in one place. Short of using css-expressions (IE only) I can't see a way of setting the outer divs width to the width of the first child element.

Community
  • 1
  • 1
Antony Scott
  • 21,690
  • 12
  • 62
  • 94
  • 1
    I normally put a width/height on images because it's better for browser rendering - no layout jumping as the page loads, and the layout is preserved when images are unavailable. In this case I guess I'd put a height on the image and it would inherit the width. – DisgruntledGoat Mar 06 '09 at 14:44
  • Also the * selector is a bad idea. I could have more elements in the caption (eg links) that might get messed up. It should be replaced with simply `img` (`duv` is 100% by default) – DisgruntledGoat Mar 06 '09 at 14:52
  • fair comment on the * selector – Antony Scott Mar 06 '09 at 15:00
2

I had the same problem and after reading this decided to use an inline-style on the surrounding element. Seems the better solution over using a table to me.

user73912
  • 49
  • 4
2

You can also acheive this using the following solution proposed by Temani Afif in his blog post (All credits to him, I just don't want the solution to be forgotten)

<div class="box">
   <img>
   <h1>Lorem ipsum dolor ..</h1>
</div>
.box {
  display: inline-block;
}
h1 {
  width: 0;
  min-width: 100%;
}

Make the container inline-block, and makes the h1 (or whatever text tag you use) occupy the space dictated by the sibling element. It's essentially a hack, but it works! No unintended semantic consequences like the table solutions

sayandcode
  • 1,775
  • 1
  • 11
  • 24
0

You could use the display:table solution for all other browsers, and a CSS Behaviour for Internet Explorer.

doekman
  • 18,750
  • 20
  • 65
  • 86