I am trying to determine the best way to create an accessible accordion/list that has sub-headers (or group separators/collapsible headers, if you will).
To illustrate, this is how a default one would look (schematically):
Some of the items are clickable (and provide a hint to that by changing the background color and changing the cursor) and some are not (like "List item 13").
Some (or all) sub-headers may be collapsible (with some additional hints added later):
Now, the structure can be implemented in several possible ways:
Option 1. To hell with standards and accessibility
<ul>
<div class="header"><a href="...">Header 1</div>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
<li><span>List item 13</span></li>
<div class="header"><a href="...">Header 2</div>
<li><a href="...">List item 21</a></li>
<li><span>List item 22</span></li>
</ul>
This one does work. It is not accessible and doesn't pass HTML validation, but it works.
Option 2. Well, at least it passes validator
<ul>
<li class="header"><a href="...">Header 1</a></li>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
<li><span>List item 13</span></li>
<li class="header"><a href="...">Header 2</a></li>
<li><a href="...">List item 21</a></li>
<li><span>List item 22</span></li>
</ul>
This one passes validation and is accessible to an extent, but doesn't allow for distinction (as far as screen readers go) between a header and a regular clickable list item.
Options 3. TL;DR
<ul>
<li>
<a class="header" href="...">Header 1</a>
<ul>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
</ul>
</li>
<li>
<a class="header" href="...">Header 2</a>
<ul>
<li><a href="javascript:;">List item 21</a></li>
<li><span>List item 22</span></li>
</ul>
</li>
</ul>
This one, or some more thought-out variation of it seems to be the one. Accessible, as I assume outer or inner bullets should be read properly by a screen reader and passes validation.
It's just a bit more PITA to code and maintain. Both from JS and CSS perspective and especially if it's a plugin that is intended to be extended and customized.
So the question is - which one, if any, of the above would be better. Or, alternatively, what would be the ultimate accordion/list implementation? (which, from my experience, may be a pipe dream)
Screen reader users can navigate a page according to its headings, listen to a list of all headings, and skip to a desired heading to begin reading at that point. Screen reader users can use headings to skip the repeated blocks of content like headers, menus, and sidebars, for example.
The page must contain at least one h1 element identifying and describing the main content of the page. An h1 heading provides an important navigation point for users of assistive technologies, allowing them to easily find the main content of the page.
To facilitate navigation and understanding of the overall page structure, authors should use headings that are properly nested. Example: h1 followed by h2, h2 followed by h2 or h3, h3 followed by h3 or h4, and so on.
The third option beats the other two by far in terms of accessibility. If the accordion/list did have a lot of content then it may be worth adding headings (<h1>
, <h2>
, etc.) to each of the list items. This would provide more semantic structure to the page which would be helpful to users using assistive technology.
<h1>Some sections</h1>
<ul>
<li>
<h2><a class="header" href="...">Header 1</a></h2>
<ul>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
</ul>
</li>
<li>
<h2><a class="header" href="...">Header 2</a></h2>
<ul>
<li><a href="javascript:;">List item 21</a></li>
<li>List item 22</li>
</ul>
</li>
</ul>
The third option is also the nicest to style and manipulate with JavaScript due to its hierarchical nature.
There was a discussion about implied and explicit sections in the comments so I thought I would address it. I attempted to download the HTML5 Outlier Chrome extension to test this but unfortunately it didn't seem to show up in the bar. Here is how I understand it:
The sectioning root elements in HTML5 are:
<body>
<blockquote>
<details>
<fieldset>
<figure>
<td>
<nav>
<aside>
<footer>
<header>
Since none of them are present the sections are implicit from the usage of the heading elements much like in HTML4 so the document outline for the markup above would look like this:
Some sections
1.1. Header 1
1.2. Header 2
This is exactly what we expect and what we want. This is from unor's comment
It's allowed syntactically. But it would be an issue for the document outline: the start of a new section (→ opening li), introduced by the heading, would still be part of the previous section. If you use the section (or any other sectioning element) expliclty, the start and end of that section is clearly specified.
I believe he's saying that the <li>
before '1.1. Header 1' would be part of the section '1. Some sections' which is true and I'm my opinion not a problem as the <li>
should belong to the section above. The usage of a sectioning root element like <section>
to explicitly define a section block would lead to very much the same result as we had previously:
<ul>
<li>
<section>
<h2><a class="header" href="...">Header 1</a></h2>
<ul>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
</ul>
</section>
</li>
I'm of the opinion (can't find a source) that implicit sectioning is just as 'scoped' as explicit sectioning would be. Since the document outline is a list the </li>
after the </section>
in the above would still be part of 1.1 Header 1 according to the document outline like this.
<!-- start 1. Some sections -->
<h1>Some sections</h1>
<ul>
<li>
<section>
<!-- start 1.1. Header 1 -->
<h2><a class="header" href="...">Header 1</a></h2>
<ul>
<li><a href="...">List item 11</a></li>
<li><a href="...">List item 12</a></li>
</ul>
</section>
</li>
<li>
<!-- end 1.1. Header 1 -->
<section>
<!-- start 1.2. Header 2 -->
<h2><a class="header" href="...">Header 2</a></h2>
<ul>
<li><a href="javascript:;">List item 21</a></li>
<li>List item 22</li>
</ul>
</section>
</li>
</ul>
<!-- end 1. Some sections -->
That is to say, once you start a sub-section you cannot end it until you start another section so </li><li>
would be included at the end of '1.1. Header 1' and also included in its parent section '1. Some sections'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With