117

What is the proper way to provide a semantic caption for an HTML list? For example, the following list has a "title"/"caption".

Fruit

  • Apple
  • Pear
  • Orange

How should the word "fruit" be handled, in a such way that it is semantically associated with the list itself?

Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
Jon P
  • 19,442
  • 8
  • 49
  • 72
  • The HTML specifications need to add caption, legend and note attributes or tags to elements. Images, tables, lists and other non-text objects have a title, legend and/or note attached to it in publications, and a useful markup language needs to reflect that convention. –  Jan 24 '15 at 10:56
  • 12
    I'm surprised this question has been closed; it's clearly about semantics, not aesthetics, or any other subjective topic. The question is directly asking "Is there an appropriate semantic markup for this situation?" and, insofar as HTML5 is concerned, the answer is ["yes"](http://stackoverflow.com/a/35019847/889583). – daiscog Feb 20 '17 at 09:41
  • 13
    I'm tired of seeing so many questions which are of my interest as being closed as "opinion-based". It is a contraproductive. Let us express our opinions. Also, this question is about "best practice". People can have valid arguments regarding best practices (with sources). We want those arguments. Its not all about "opinions" – Mladen Adamovic May 27 '17 at 16:28
  • 4
    I've voted to re-open this question and edited it to sound less opinion-y. Now it clearly asks for a correct semantic way to add a title. – Lazar Ljubenović Nov 14 '18 at 09:49

10 Answers10

97

Option 1

HTML5 has the figure and figcaption elements, which I find work quite nicely.

Example:

<figure>
    <figcaption>Fruit</figcaption>
    <ul>
        <li>Apple</li>
        <li>Pear</li>
        <li>Orange</li>
    </ul>
</figure>

These are then easily styled with CSS.


Option 2

Using CSS3's ::before pseudo-element can be a nice solution:

HTML:

<ul title="Fruit">
    <li>Apple</li>
    <li>Pear</li>
    <li>Orange</li>
</ul>

CSS:

ul[title]::before {
    content: attr(title);
    /* then add some nice styling as needed, eg: */
    display: block;
    font-weight: bold;
    padding: 4px;
}

You can, of course, use a different selector than ul[title]; for example, you could add a 'title-as-header' class and use ul.title-as-header::before instead, or whatever you need.

This does have the side effect of giving you a tooltip for the whole list. If you don't want such a tooltip, you could use a data attribute instead (e.g., <ul data-title="fruit"> and ul[data-title]::before { content: attr(data-title); }).

daiscog
  • 11,441
  • 6
  • 50
  • 62
  • Your answer is what the specs is saying. I wonder why it's not the top voted one. – Ahmed Mahmoud Mar 07 '19 at 08:33
  • @AhmedMahmoud Probably because the top answer is 7 years older than this one! – daiscog Mar 07 '19 at 09:30
  • Oh, the time flies. Didn't notice the date. – Ahmed Mahmoud Mar 07 '19 at 11:49
  • does that mean `figure` can be used with content different from images? – CodeGust Sep 04 '20 at 01:11
  • 1
    @CodeGust [absolutely](https://html.spec.whatwg.org/#the-figure-element) – daiscog Sep 07 '20 at 14:39
  • @daiscog yes, but "is typically referenced as a single unit from the main flow of the document." -- wouldn't `figure` make the semantic meaning of an element less important/meaningful than simple h3/aria-labelledby if that is something like a sitemap in the footer with a page-caption and a list of subsections? – CodeGust Sep 19 '20 at 17:33
  • @CodeGust i don't think it makes it less `important/meaningful`. The decision about which approach to use should ultimately be guided by the context in which the list is being presented. `hX` elements are document section headers; everything under the `h3` until the next `hX` is part of the section headed by it. The `h3` approach may be appropriate or may not. It depends on the circumstances. – daiscog Oct 12 '20 at 12:31
  • Option 2 for the win. – Mike Finch Oct 12 '22 at 16:53
  • @MikeFinch yeah I really like option 2, but it does have some downsides. First, you get the browser's title tooltip when hovering the cursor over the list (minor, you might actually like that). But also, I've no idea how well that works with screenreaders or other assistive tech, as I've not looked into it. – daiscog Oct 14 '22 at 13:06
  • 1
    To be more specific, option 2, where you use a data-title attribute, for the win. That is what I ended up using. – Mike Finch Oct 18 '22 at 00:19
87

While there is no caption or heading element structuring your markup effectively can have the same effect. Here are some suggestions:

Nested List

<ul>
    <li>
        Fruit
        <ul>
            <li>Apple</li>
            <li>Pear</li>
            <li>Organge</li>
        </ul>
    </li>
</ul>

Heading Prior to List

<hX>Fruit</hX>
<ul>
    <li>Apple</li>
    <li>Pear</li>
    <li>Orange</li>
</ul>

Definition List

<dl>
  <dt>Fruit</dt>
  <dd>Apple</dd>
  <dd>Pear</dd>
  <dd>Orange</dd>
</dl>
gyre
  • 16,369
  • 3
  • 37
  • 47
ahsteele
  • 26,243
  • 28
  • 134
  • 248
  • I'm going with this as my chosen answer as after doing some more research the Definition list will probably fill me needs here as there will be multiple lists. Styling will now be my next challenge. – Jon P Jul 17 '09 at 06:30
  • 2
    @alohci If there are going to be more definitions in the list what's wrong w/ a definition list or an unordered list? – ahsteele Jul 17 '09 at 13:38
  • 2
    @Alohci: Please elaborate. Intrigued by your comment but as it stands it's not helpful at all as you don't explain *why* the other options are not 'semantically valid' – Stijn de Witt Apr 14 '14 at 11:31
  • 1
    @StijndeWitt - Well, that was nearly 5 years ago. Apple, Pear and Orange are not definitions of fruit. That rules out option 3. In option 1, the outer list's contents are not a list. – Alohci Apr 14 '14 at 13:11
  • 1
    Lol, sorry I didn't look at the date! Very cool of you to respond anyway :) Re Option 1: Seems to me a list with one item in it is not invalid... At least in my mind having Apple, Pear and Orange be subitems of the broader item Fruit does make some sense. I can see how you could expand the outer list with entries like 'Vegetable', 'Meat' etc – Stijn de Witt Apr 14 '14 at 13:47
  • 4
    @StijndeWitt - That's all true. It's incorrect semantics in *this* instance only because that's not in the question. That's the problem with getting HTML markup correct, the actual content and the context it's in matters. – Alohci Apr 14 '14 at 16:38
  • I respect semantically valid html moreso than most people I think, but sometimes the tags available in the html5 library seem so arbitrary, much less w3c's definitions of them. Makes me wonder whether the effort I go through to ensure my html5 makes sense is worth the while. Regardless, I think allowing a header within
      or
      would be helpful.
    – aaaaaa Feb 19 '15 at 21:06
  • I love this answer, but wanted to add one (not confident enough to add to the answer) I often use: `

    There are several types of fruit that are useful in this case:

    • Apple
    • Pear
    • Orange
    `
    – Jefferey Cave Dec 31 '15 at 15:30
  • 2
    @JeffereyCave Having a `
      ` (or any other block-level element) as a child of a `

      ` is invalid according to [the HTML specification](https://www.w3.org/TR/html5/grouping-content.html#the-p-element), which states that `

      ` can only have "phrasing content" as child nodes.

    – daiscog Jan 26 '16 at 16:58
  • @daiscog You are correct, HTML specifically mentions this case as invalid. I disagree with their distinction between structure and logic, but while I await my seat on the committee, I will have to change my notation. – Jefferey Cave Jan 26 '16 at 17:16
  • It is a "Description List," not a "Definition List." If we're talking about semantics, that's an important distinction. And so far, Description is the only thing that allows you to add a more emphasized item without nesting. – RoboticRenaissance Sep 05 '16 at 14:52
  • 1
    @RoboticRenaissance according to the W3C it's a definition list: https://www.w3.org/TR/html4/struct/lists.html#h-10.3. – ahsteele Sep 08 '16 at 19:11
  • 4
    @ahsteele Interesting... MDN has it listed as Description List... Oh! "Prior to HTML5, [it] was known as a definition list." https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl. Your link was for html4. And on that link, they give an example of a dl representing a dialog, with each dt marking the speaker and dd having what they say. So I'm pretty sure they, whatever they're called, can properly be used as in this way as well. – RoboticRenaissance Sep 08 '16 at 19:22
  • @RoboticRenaissance that is good information. Agreed the approach seems appropriate. – ahsteele Sep 08 '16 at 19:23
14

As far as I know, there are no provisions in current HTML specs for providing a caption for a list, as there are with tables. I'd stay with using either a classed paragraph, or a header tag for now.

<h3>Fruit</h3>
<ul>
    <li>Apple</li>
    <li>Pear</li>
    <li>Orange</li>
</ul>

In the future, when HTML5 gains wider adoption, you will be able to use the <legend> and <figure> tags to accomplish this slightly more semantically.

See this post on the W3C mailing list for more information.

sixthgear
  • 6,390
  • 2
  • 22
  • 17
13

To ensure screen readers connect the list to an associated heading, you could use aria-labelledby connected to a heading with an id like so:

<h3 id="fruit-id">Fruit</h3>

<ul aria-labelledby="fruit-id">
  <li>Apple</li>
  <li>Pear</li>
  <li>Orange</li>
</ul>

As noted in a previous answer, make sure your heading level follows heading order in your document.

Corey Bruyere
  • 786
  • 1
  • 10
  • 21
  • 1
    This answer seems to address the programmatic connection between the `H#` and the `UL` very well. – Alan May 31 '22 at 15:45
1

There is no caption-like tag for a list like a table has. So I'd just give it an <Hx> (x depending on your previously used headers).

I.devries
  • 8,747
  • 1
  • 27
  • 29
0

I think the most accepted answer's first approach is not really semantic as it will say it is a figure when it is not. The second approach is a little better for who is reading the HTML code itself, but I think most screen readears will ignore pseudoelements when reading out loud, at least ChromeVox does.

The most semantic way I thought of and ChromeVox does read it the right way (reads the title and say it is a list with n items):

<h2 id="list-title" aria-hidden="true">Fruits:</h2>
<ul role="list" aria-labelledby="list-title">
    <li>Apple</li>
    <li>Pear</li>
    <li>Oranges</li>
</ul>

There is an issue that the user won't be able to read only the title of the list, instead when the first item is selected it will read:

  1. The title
  2. Inform it is a list with n items
  3. Read the item itself and inform it is a list item.

EDIT

If you want people to find the list by the heading itself you should remove aria-hidden. But as there are already shortcuts for navigating through lists, keeping the header navigation can make it ambiguous.

caiohamamura
  • 2,260
  • 21
  • 23
  • Neither of these is actually valid HTML. `caption` [must be a child of `table`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption) and [`div` is not a valid parent of `li`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li) – Jon P Aug 10 '23 at 03:47
  • I edited that and provided a solution which will work for `NDVA` which most blind users use and `ChromeVox`, but won't work for `Windows Narrator`. They should agree in a standard for accessibility, it looks like the beggining of the browsers when each one would render/interpret `HTML/CSS/JS` in their own way. – caiohamamura Aug 10 '23 at 17:05
  • Is there any substantial difference to [this answer](https://stackoverflow.com/a/61507965/4665) ? Note the question is regarding *semantic html* not *accessibility* – Jon P Aug 11 '23 at 01:10
  • In my point of view `HTML` is only right if you write it with accessibility in mind. The results will often be more semantic and easier to understand by everyone. I'm not saying that I never write bad `HTML`, but I would write better ones if I was educated to write semantic and accessible `HTML`, unfortunately I wasn't, I'm just trying to change that for the ones learning from now on. – caiohamamura Aug 24 '23 at 17:56
-1

I know this is old but wanted to add the answer that I found for future people: https://www.w3.org/MarkUp/html3/listheader.html

use the <lh> element:

<ul>
  <lh>Types of fruit:</lh>
  <li>Apple</li>
  <li>Orange</li>
  <li>Grape</li>
</ul>
rnewman
  • 15
  • 1
  • 4
    Note: this was mentioned in a draft of [HTML 3.0](https://www.w3.org/MarkUp/html3/html3.txt) but never included in [HTML 3.2](https://www.w3.org/TR/2018/SPSD-html32-20180315/) so while it may render properly in some browsers it's not supported. – Nathan Champion Sep 10 '20 at 13:35
-1
<ul>
  <p>YOUR CAPTION</p>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

It works. But i'm not sure that is the best way, i'm just a beginner

-2

Since I was trying to find a solution with older browser support, I have what might be an over-simplified solution. Using table display styles and ids/classes:

    <ul>
        <li id="listCaption">My List</li>
        <li>first item</li>
        <li>second item</li>
        <li>third item</li>
      </ul>

Then apply the display: table-row; style to the element in CSS:

    li#listCaption {
      display: table-row;
      font-size: larger;
      text-decoration: underline; }

This works much better if you are using a description list, which is what I was doing when I had the same question. In that case, you can use <div> in the HTML and display: table-caption; in CSS, as div elements are supported within the dl list:

    <dl>
        <div id="caption">Table Caption</div>
        <dt>term</dt>
        <dd>definition</dd>
    </dl>

In CSS you can apply various styles to the caption:

    #caption {
        display: table-caption;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 20px;
        background: transparent;
        caption-side: top;
        text-align: center; }

I should note that table-caption does not work as well in ul/ol as it is treated as a block element and the text will be aligned vertically, which you probably don't want.

I tested this in both Firefox and Chrome.

harrekki
  • 1
  • 2
-3

You can always use <label/> to associate label to your list element:

<div>
    <label for="list-2">TEST</label>
    <ul id="list-1">
        <li>one</li>
        <li>two</li>
        <li>three</li>
    </ul>
    <label for="list-2">TEST</label>
    <ol id="list-2">
        <li>one</li>
        <li>two</li>
        <li>three</li>
    </ul>
</div>
HelpNeeder
  • 6,383
  • 24
  • 91
  • 155
  • 5
    This is invalid. The [HTML spec](https://html.spec.whatwg.org/multipage/forms.html#attr-label-for) states that the `for` attribute **must** be the ID of a _labelable element_, which `UL` (at time of writing) [is not](https://html.spec.whatwg.org/multipage/forms.html#category-label). – daiscog May 04 '20 at 09:52