Monday, 24 November 2008

CSS, Picture Gallery Style


Last week's entry spoke about displaying a list of items with several items across the page. We could call that picture gallery style; it looks rather like the thumbnail view in Windows Explorer. See the picture above.

Given that we're building our web pages in standards-compliant XHTML, positioning everything with CSS and not using tables, how do we lay out the images and their associated text? The obvious way to do this is to place each image and its caption inside a DIV element, and then style the DIVs using float: left. It couldn't be easier to generate the HTML. Each image gets simple markup, like this:

<div class="picture">
<img src="..."/>
<p>The Famous Crack in the Tate Gallery Floor</p>
</div>


and the CSS could hardly be simpler, either:

.picture { width: 150px; float: left; }

This is easy to code, and has the advantage that, if the page layout is liquid and allows the user to change the width, our pictures will move around too, displaying four, five, or more pictures across the width of the page. When you try it out, there are some problems:
  1. floated elements do not force their container to extend its height. If your picture DIVs are enclosed in something with a border, you will have to resort to trickery to get the border to expand around the pictures: either assign an explicit height to the container, or add some dummy content so that you can style it with clear: both.
  2. to make the captions word-wrap at a suitable width, you have to style the picture DIVs with an explicit width, as shown in the example above.
  3. if the picture DIVs have different heights, you may find that they don't stack properly, as shown in this picture:

This happens because the browser thinks that the third and fourth pictures can be flowed around the first two, as if they were text. That's exactly the correct interpretation of float: left, but it's not what we expect for this page. The only answer seems to be to assign an explicit height to each picture DIV, as well as the explicit width. That causes problems of its own in dealing with long captions: either they get truncated, or they overlap the picture below, or you need to allow for scrollbars.

For me, this is a case where an HTML table is fully justified. The only slight difficulty comes in dividing the list of pictures up in to rows, but that's very easy using the Struts 2 tag library, as shown in my previous post. Most systems for generating HTML can do the same thing almost as easily.

The markup for each picture is almost the same. Instead of <div class="picture">, we change the DIV tag to TD, making it <td class="picture">, and the CSS rule becomes this:

.picture { width: 150px; vertical-align: top; }

The resulting page looks like this:

No comments: