Image captions in XHTML

Here’s a quick XHTML tip. Image captions sometimes present a bit of a puzzle to people trying to do proper semantic markup. The result is that either completely the wrong markup gets used (a caption is not a paragraph) or absolutely no semantic markup is used and the image and caption are simply wrapped in <div>s and <span>s, the generic block and inline elements.

In fact the proper way to attach a caption to an image is to use a definition list (<dl>). A definition list is a list of pairs of elements, a definition term (<dt>) and a definition description (<dd>); the first is an item about which the second gives further information, which is exactly the relation between an image and its caption. The “definition” in “definition list” is potentially misleading. Presumably it’s called that for want of anything better. The important thing to note is that each list item is a pair: a term followed by its description. (Actually, definition lists are a little more complicated than that. See comment 4.)

So, here’s how to markup an image and its caption:

<dl class="image">
  <dt>
    <img />
  </dt>
  <dd>
    caption
  </dd>
</dl>

All that’s needed is some CSS to give us the right visual presentation:

/* this first rule is probably unnecessary, */
/* but better safe than sorry               */
dl.image,
dl.image dt,
dl.image dd {
  display : block ;
  list-style-type : none ;
}
dl.image {
  margin : 1.2em auto ;
  border : none ;
  padding : 0 1.2em ;
  text-align : center ;
}
dl.image dt {
  margin : 0 ;
  border : none ;
  padding : 0 ;
}
dl.image dt img {
  display : block ;
  margin : 0 auto ;
  border : 1px dotted #38abc8 ;
  padding : 15px ;
  color : #38abc8 ;
  background : #eee ;
}
dl.image dd {
  margin : 0 ;
  border : none ;
  padding : 1ex 1ex 0 1ex ;
  font-size : 90% ;
  font-style : italic ;
  color : #38abc8 ;
}

and the result will look like this:

Mmmm … Scarlett Johansson, she purdy

Of course, that was just an excuse to put a picture of Scarlett Johansson on my blog.

The only semantic issue that might give one pause for thought is whether a list can contain only one item—or pair, in this case. I would suggest that any misgivings about that are misplaced. A list with no items is no list at all. But a list with only one item strikes me as a perfectly legitimate limit case of a list.

17 Responses to “Image captions in XHTML”

  1. Chris Says:

    Crikey - and I thought little girls were made of sugar, spice and all things nice. Darren - please can you teach me code?

  2. Kris Says:

    The correctness of this visual presentation has nothing to do with CSS.

  3. Darren Brierton Says:

    Heh. I’m pleased you liked the picture Kris. And Chris, just keep reading. I think I’m going to make the “Tips’N'Tricks” thing a regular feature.

  4. Darren Brierton Says:

    Footnote/Addendum—more on the <dl> element:

    In the original post I simplified things slightly. I said that a <dl> element contained pairs (indeed, I implied that they were ordered pairs) of <dt> and <dd> elements. However, that is not required by the DTD. The semantics of definition lists is implicit rather than explicit. A <dl> element can contain any old mish-mash of <dt> and <dd> elements and still be valid. It might not, however, make any sense (compare the sentence “All green ideas sleep furiously”—it’s syntactically (grammatically) correct, i.e. it conforms to the “DTD” for English, it just doesn’t mean anything). In particular, these next two examples are perfectly valid but quite meaningless:

    A term with no description:

    <dl>
      <dt>
        foo
      </dt>
    </dl>

    A description with no term:

    <dl>
      <dd>
        bar
      </dd>
    </dl>

    The semantics of definition lists is implicit in the ordering of the <dt> and <dd> elements (as opposed, say, to it being made explicit through the use of id and idref attributes, or through nesting the elements). So, this next example also makes no sense:

    A description preceding the term it describes:

    <dl>
      <dd>
        bar
      </dd>
      <dt>
        foo
      </dt>
    </dl>

    However, more than one term can be associated with a single description, and more than one description can be associated with a term, in ways which are both valid and meaningful:

    <dl class="dictionary">
      <dt>
        bank
      </dt>
      <dd>
        1. Somewhere you deposit your money.
      </dd>
      <dd>
        2. The side of a river.
      </dd>
      <dt>
        geek
      </dt>
      <dt>
        nerd
      </dt>
      <dd>
        Someone who is just misunderstood by the computer
        illiterate imbeciles around them.
      </dd>
    </dl>

    Definition lists are one of the most underused parts of XHTML, which is a shame as they are a powerful tool. However, their implicit semantics also indicate why XHTML, whilst being far more semantically expressive than most people give it credit for, is also quite semantically weak.

  5. Phlogiston » Blog Archive » Image captions in XHTML Says:

    […] d by its description. (Actually, definition lists are a little more complicated than that. See comment 4.) So, here’s how to markup an image […]

  6. Sven Lehr Says:

    How about if you wanted to image/caption pairs beside each other? Say I wanted to use definition lists to make my page look like this: IMG1IMG2CAP1CAP2.

  7. Sven Lehr Says:

    Sorry that post didn’t come out right. (I used some HTML.) Here’s what I mean:

    IMG1 IMG2 IMG3 IMG4
    CAP1 CAP2 CAP3 CAP4

    Can you style a dl to do that?

    Sven

  8. Darren Brierton Says:

    Sven Lehr: Yes that is both a commonly desired layout and a tricky thing to achieve with the technique I described here. Ideally you’d want to wrap each pair of dt and dd elements in a container, but you can’t because the DTD says only dt and dd elements can be children of dl elements.

    What you’d need to do is to place each image and its caption in their own dl element, and float the dls next to each other. So, you’d end up with something like this:

    <dl class="img_col">
      <dt>
        <img src="IMG1" />
      </dt>
      <dd>
        CAP1
      </dd>
    </dl>
    <dl class="img_col">
      <dt>
        <img src="IMG2" />
      </dt>
      <dd>
        CAP2
      </dd>
    </dl>
    <dl class="img_col">
      <dt>
        <img src="IMG3" />
      </dt>
      <dd>
        CAP3
      </dd>
    </dl>
    <dl class="img_col">
      <dt>
        <img src="IMG4" />
      </dt>
      <dd>
        CAP4
      </dd>
    </dl>

    Then you have a style rule that says something like:

    dl.img_col
      {
        float: left;
        margin-right: 0.5ex;
      }

    It’s not perfect, not at all, but I do think that it preserves more of the semantics than any of the other alternatives.

  9. Darren Brierton Says:

    BTW, I shoould point out that a server failure ate my theme, so the style rules regarding images and captions are currently unavailable, so you can’t really see what I was going on about. The original theme is being resurrected, but I’ve just been too busy to finish it off.

  10. Jordan Says:

    One thing that has always been an issue for me is that I can never get images and captions to look right if they are inserted somewhere in the middle of a paragraph. A lot of times in a blog, you want the image to appear right in the middle. Of course, you can’t put DIV tags inside of paragraph tags, and yet I want the image to align left or right, but have the caption centered perfectly underneath the image. Is there a clean way of doing this? I usually get fed up and stick a table in there. (gasp)

  11. Michael Warner II Says:

    I was working with DIV tags which did not make semantic sense, untill I found your page which is the only one that I found which gave a semantical solution to image captions. Thanks a lot!
    I tried to get the caption to go right of of image and force the H2 header after to not flow up and into the right of the image . IE6 would not honor the lign breaking after the DL, so I added height: 0 to it which then made IE6 line break after the DL.

    CAPTION

    TOPIC

  12. Jeff Says:

    I’m trying to solve this same problem for a webzine that’s designed for maximum accessibility, and I’m very glad I found your blog entry. This is a very cool solution, though I still wish that the XHTML standards had anticipated the need for captions and built in a solution from the start.

    Like Sven, I guess, I’m thinking about more complex visual layouts with photos. A definition list is structurally a kind of cascade, whereas it’s our natural expectation (carried over from old media) that photos will be displayed in a way that is more grid-like.

    So I wonder if you might also consider using tables for this? Would that be semantically correct? In the simplest form, you might use a single cell per row in a two-row table, with the picture in the top cell and the caption in the bottom one. CSS would be used to style the table however you like, and maybe the only choice for me would be to turn off borders.

    Figure 1

    This is the caption for Figure 1. It can be a long caption, if you like.

    Would this also be semantically correct? I know that tables are not meant to be used for layout, but it seems to me that a photo and caption are inherently related “data,” just as you infer by relating the caption as a kind of definition … so the function of the table in this case is relational, with layout being an equal or secondary function.

  13. Jeff Says:

    Sorry. I entered XHTML code on the submission form without coding it as such … This was my suggestion if you think tables would be an appropriate way to do captions:

    Figure 1

    This is the caption for Figure 1. It can be a long caption, if you like.

  14. Jeff Says:

    Maybe this’ll get it:

    Figure 1

    This is the caption for Figure 1. It can be a long caption, if you like.

  15. Jeff Says:

    … or not! Imagine the brackets [ ] as guillemets () …

    [table class=”image”]
    [tr][th]Figure 1[/th][/tr]
    [tr][td][img src=”figure1.gif” width=”100%” /][/td][/tr]
    [tr][td]This is the caption for Figure 1. It can be a long caption, if you like.[/td][/tr]
    [/table]

  16. Darren Brierton Says:

    Hi Jeff!

    I don’t think a table would be a totally inappropriate way of laying out a series of images and their captions. But I don’t think it ideal. For example your markup determines how many columns there are, and therefore how many images (and captions) appear side-by-side, regardless of width of containing block. That isn’t very fluid. I still think you would be better off using a seperate dl element for each image and its caption, and then in CSS fixing the height and width of the dls and giving them a float property (right or left, doesn’t matter). That way you get a similar effect to the table, but the number of columns expands and contracts to fit the available space.

  17. Jeff Says:

    Thanks, Darren. I’m very happy to know that I’m not the only person trying to resolve this in a way that’s both accessible and semantically correct!

    Struggled much of the day yesterday creating and troubleshooting just such a table (for an intranet, or I’d post the link), and it looked great in Firefox and shattered the layout in IE6. I was able to resolve most of those problems, but I’m back to give your solution a try instead.

Leave a Reply


Bad Behavior has blocked 152 access attempts in the last 7 days.

Creative Commons License
This work is licensed under a Creative Commons License.