How to semantically provide a caption, title or label for a list in HTML
Asked Answered
I

10

126

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?

Imco answered 17/7, 2009 at 6:15 Comment(4)
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.Olein
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".Superimposed
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"Yaw
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.Vaccine
S
105

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:

ul[title]::before {
  content: attr(title);
  /* then add some nice styling as needed, eg: */
  display: block;
  font-weight: bold;
  padding: 4px;
}
<ul title="Fruit">
  <li>Apple</li>
  <li>Pear</li>
  <li>Orange</li>
</ul>

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 the aria-label attribute instead (e.g., <ul aria-label="fruit"> and ul[aria-label]::before { content: attr(aria-label); }).

Superimposed answered 26/1, 2016 at 17:19 Comment(11)
Your answer is what the specs is saying. I wonder why it's not the top voted one.Artisan
@AhmedMahmoud Probably because the top answer is 7 years older than this one!Superimposed
Oh, the time flies. Didn't notice the date.Artisan
does that mean figure can be used with content different from images?Postgraduate
@Postgraduate absolutelySuperimposed
@Superimposed 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?Postgraduate
@Postgraduate 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.Superimposed
Option 2 for the win.Broadside
@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.Superimposed
To be more specific, option 2, where you use a data-title attribute, for the win. That is what I ended up using.Broadside
The figure element can thus be used to annotate illustrations, diagrams, photos, code listings, etc.Jeopardy
O
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>
Obmutescence answered 17/7, 2009 at 6:26 Comment(14)
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.Imco
@alohci If there are going to be more definitions in the list what's wrong w/ a definition list or an unordered list?Obmutescence
@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'Norenenorfleet
@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.Zahn
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' etcNorenenorfleet
@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.Zahn
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 <ol> or <ul> would be helpful.Quaff
I love this answer, but wanted to add one (not confident enough to add to the answer) I often use: <p>There are several types of fruit that are useful in this case: <ul><li>Apple</li><li>Pear</li><li>Orange</li></ul></p>Relevance
@JeffereyCave Having a <ul> (or any other block-level element) as a child of a <p> is invalid according to the HTML specification, which states that <p> can only have "phrasing content" as child nodes.Superimposed
@Superimposed 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.Relevance
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.Parnassus
@Parnassus according to the W3C it's a definition list: w3.org/TR/html4/struct/lists.html#h-10.3.Obmutescence
@Obmutescence Interesting... MDN has it listed as Description List... Oh! "Prior to HTML5, [it] was known as a definition list." 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.Parnassus
@Parnassus that is good information. Agreed the approach seems appropriate.Obmutescence
G
16

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.

Greave answered 29/4, 2020 at 17:33 Comment(2)
This answer seems to address the programmatic connection between the H# and the UL very well.Recency
Side note: make sure your heading tags follow a logical order and do not skip any levels... ie: h1 to h2 to h3 etc.Gervase
U
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.

Unrivalled answered 17/7, 2009 at 6:27 Comment(0)
A
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).

Alroi answered 17/7, 2009 at 6:22 Comment(0)
S
1

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 readers 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.

Screeching answered 10/8, 2023 at 2:19 Comment(4)
Neither of these is actually valid HTML. caption must be a child of table and div is not a valid parent of liImco
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.Screeching
Is there any substantial difference to this answer ? Note the question is regarding semantic html not accessibilityImco
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.Screeching
S
-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>
Schlessel answered 10/9, 2020 at 12:49 Comment(1)
Note: this was mentioned in a draft of HTML 3.0 but never included in HTML 3.2 so while it may render properly in some browsers it's not supported.Cognoscenti
C
-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

Cooperstein answered 14/11, 2022 at 16:49 Comment(1)
It may "work" but it is invalid HTML.Imco
T
-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.

Thais answered 16/10, 2020 at 20:53 Comment(0)
W
-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>
Wendeline answered 9/3, 2019 at 2:16 Comment(1)
This is invalid. The HTML spec states that the for attribute must be the ID of a labelable element, which UL (at time of writing) is not.Superimposed

© 2022 - 2024 — McMap. All rights reserved.