One of those should-be-simple-but-usually-isn’t scenarios we frequently encounter with CSS is adding a caption beneath an image thumbnail. When this was done with tables every image and caption would be in a table cell and the row would expand to the height of the tallest cell. But with the advent of CSS layouts it was common to put the images in a list and float each list item. Thus the challenge: if we don’t know and can’t control the length of the caption, the grid would get thrown off by a long caption (see image below).

Mis-aligned image captions -- whenever a caption is slightly longer the next row has missing images

The most common ways of solving this problem have been variations upon:

  1. Try to restrict the captions to a certain length, set a height on the list item, and don’t let anything overflow the list item vertically.
  2. Try to restrict the captions to a certain length, don’t let the captions wrap, and don’t let anything overflow the list item horizontally.
  3. Use display:inline-block on the list items instead of floating the list items.

The inline-block method has been the only real way to achieve the desired effect of a grid of image thumbnails with captions of varying lengths. The only issue is browser support — some haven’t supported inline-block and some have only supported inline-block with a lot of bugs.

Floating captions with CSS3 :nth-child

Today I recognized another method. Now, it’s no better than inline-block because it relies on CSS3 :nth-child selectors. It therefore has the same downfall of inconsistent browser support. Less support than inline-block! I imagine inline-block will be totally reliable long before this CSS3 :nth-child alternative. (In fact, I might consider it totally reliable now if the project didn’t require very much backward compatibility — older versions of Firefox [of all browsers!] being a major culprit.)

However, I thought this was interesting. Below is the code, but you might want to go ahead and look at the demonstration at CSS3 :nth-child floating image captions.

<ul class="media-list">
	<li class="media-item">
		<a class="media-link" href="#1">
			<img class="media-thumb" src="#" alt="" width="176" height="132" />
			<span class="media-label">Media Label Name Media Label Name Media Label Name Media Label Name</span>
		</a>
	</li>
	<li class="media-item">
		<a class="media-link" href="#2">
			<img class="media-thumb" src="#" alt="" width="176" height="132" />
			<span class="media-label">Media Label Name</span>
		</a>
	</li>
	<li class="media-item">
		<a class="media-link" href="#3">
			<img class="media-thumb" src="#" alt="" width="176" height="132" />
			<span class="media-label">Media Label Name</span>
		</a>
	</li>
	<li class="media-item">
		<a class="media-link" href="#4">
			<img class="media-thumb" src="#" alt="" width="176" height="132" />
			<span class="media-label">Media Label Name</span>
		</a>
	</li>
</ul>

Here’s the start of the CSS which will get us to the point pictured above (with things mis-aligned). The list is reset and the list items are floated.

nav,nav ul,nav li,nav a,nav img{ display:block;margin:0;padding:0;list-type:none; /* demo reset */ }

.page-media{
	margin:0 auto;
	width:578px;
}
	.media-list{
		background:#EEE;
		overflow:hidden; /* clearfix */
	}
		.media-item{
			float:left;
			margin:0 10px 10px 0;
			padding:5px;
			width:176px;
			background:#DDD;
		}
			.media-link{}
				.media-thumb{
					margin-bottom:5px;
					background:#CCC;
				}
				.media-label{ padding:0 5px; }

Now here are the CSS :nth-child selectors to fix the issues with long captions (as well as take care of extraneous margins).

.media-item:nth-child(3n+3){
	/* 3 to a row, last in the row */
	margin-right:0;
	background:pink;
}
.media-item:nth-child(3n+4){
	/* 3 to a row, first in the row */
	clear:left;
	background:turquoise;
}
.media-item:nth-last-child(-n+3){
	/* 3 to a row, last three */
	margin-bottom:0;
	background:yellow;
}

That gives us this (see image below)!

In these good image captions the images and their captions are in a neat 3 by 3 grid.

To see it in action click on CSS3 :nth-child floating image captions.

CSS3 Columns

After I posted I thought, “You’re missing the obvious when it comes to ‘easy’. What could be easier than CSS3 columns to make, well, columns? Vertically oriented, too! Hmm…good point, I should try that out.” So I did, and it works nicely enough (though I prefer the images on each “row” starting at the same place). Or, well, it will once the whole column-break-inside:avoid / break-inside:avoid-column thing works. See the demo at CSS3 columns image gallery thumbnails with captions. Lemme know if you have a fix for avoiding column breaks inside, too!

Inline-Block Image Gallery with Captions

There was a particular site that I thought gave the best tutorial of the inline-block method, but I can’t find it right now. Here are some other good ones:

Versions of Chrome around 11 (that’s when I first noticed it) and Safari (dunno which versions, but I assume it corresponds to a Webkit build) use propriety styles for figure that include -webkit margins. Those margins aren’t currently accounted for in the demo, so it can look pretty crap on those versions.