Accordions
Accordions are common design structures used to organize and hide content, so as not to overwhelm the user. Accordions are also web structures that often require JavaScript to show/hide things based on a user click or focus event.
The key to making accordions accessible is to toggle some ARIA properties and states on user click or focus events (e.g. toggle aria-hidden
, aria-expanded
, etc.).
Best Practices
The accordion buttons and associated content are set up in an unstructured list here. This, like having navigation links in a list, allows a visually impaired user to know how many accordion elements there are, giving them a better sense of the page and content with which they are dealing.
Additionally, we placed an aria-label
on the ul
tag to let the user know explicitly that they are dealing with accordions. (The aria-label
is set to ‘Accordion Control Button Group’).
Accordion Buttons
Buttons are used as the accordions so that they are tab-able by keyboard users and accessible to screen readers.
Each accordion button has a unique
id
associated with itsaria-controls
(each button controls this particularid
which references the hidden content beneath it).- Here, the
aria-controls
for each button is:aria-controls='content-{#}'
- Here, the
Each button has an
aria-expanded
attribute on it that is toggled between true and false. Ifaria-expanded='true'
, the content associated with it is shown, and if'false'
the content is hidden. (All buttons havearia-expanded='false'
to start).
Accordion Content
Every content area has an
id
that corresponds to thearia-controls
for each button.- The content ids are:
id='#content-{#}'
- The content ids are:
Each content area has an
aria-hidden
attribute that is toggled between true or false. When true, the content is neither visible nor perceivable by screen reader, and assistive technologies will skip this content. (However, the content areas are also being set between{display: none;}
and{display: block;}
, so screen readers will most likely not read the{display: none;}
content anyways andaria-hidden
attributes may be unnecessary.
The examples below will show the HTML structure and JavaScript behavior required to make our examples work and explain each part in detail.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <div class="accordion-example"> <ul aria-label="Accordion Control Group Buttons" class="accordion-controls"> <li> <button aria-controls="content-1" aria-expanded="false" id="accordion-control-1">Apples</button> <div aria-hidden="true" id="content-1"> <p>Apples are a fine fruit often associated with good health, and fewer doctor's appointments.</p> <p>Example. An apple a day keeps the doctor away.</p> </div> </li> <li> <button aria-controls="content-2" aria-expanded="false" id="accordion-control-2">Lemons</button> <div aria-hidden="true" id="content-2"> <p>Lemons are good with almost anything, yet are often have a negative connotation when used in conversation.</p> <p>Example. The bread from the french bakery is normally very good, but the one we bought today was a lemon.</p> </div> </li> <li> <button aria-controls="content-3" aria-expanded="false" id="accordion-control-3">Kiwis</button> <div aria-hidden="true" id="content-3"> <p>Kiwis are a fun, under-appreciated fruit.</p> </div> </li> </ul> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | var accordionButtons = $('.accordion-controls li button'); function accordionToggle() { $('.accordion-controls li button').on('click', function(e) { $control = $(this); accordionContent = $control.attr('aria-controls'); checkOthers($control[0]); isAriaExp = $control.attr('aria-expanded'); newAriaExp = (isAriaExp == "false") ? "true" : "false"; $control.attr('aria-expanded', newAriaExp); isAriaHid = $('#' + accordionContent).attr('aria-hidden'); if (isAriaHid == "true") { $('#' + accordionContent).attr('aria-hidden', "false"); $('#' + accordionContent).css('display', 'block'); } else { $('#' + accordionContent).attr('aria-hidden', "true"); $('#' + accordionContent).css('display', 'none'); } }); }; function checkOthers(elem) { for (var i=0; i<accordionButtons.length; i++) { if (accordionButtons[i] != elem) { if (($(accordionButtons[i]).attr('aria-expanded')) == 'true') { $(accordionButtons[i]).attr('aria-expanded', 'false'); content = $(accordionButtons[i]).attr('aria-controls'); $('#' + content).attr('aria-hidden', 'true'); $('#' + content).css('display', 'none'); } } } }; //call this function on page load accordionToggle(); |