Introduction
The accordion widget pattern consists of a set of associated disclosure panels. Each panel can be opened or closed individually with the purpose of reducing the need to scroll through multiple sections on a page. Commonly, the accordion will typically limit it to only ONE panel open at a time. If a panel is open and the user opens another, the formerly open one closes. This comes off as a potential antipattern in that the accordion can prevent the user from comparing the content in different panels. The approach to accordions works if the panel contents are truly independent of each other. That is rarely the case.
While some accordion code examples include configuration to control how many panels can be open at a time, the accordion variation presented here is explicitly restricted. The stacked disclosure pattern explicitly prevents this antipattern by allowing any number of panels to be open (or closed at a time). Additionally, to support managing the panels, the stacked disclosure requires buttons to open or close all the panels at once.
This JavaScript library and supporting information are an open source project on GitHub released under the Mozilla Public License Version 2.0.
Example Stacked Disclosure
Example Stacked Disclosure Link
The example below, Cat Coat Patterns,
showcases the basic features of the stacked disclosure in
action. At the top of the widget is an <H3>
that names the entire widget. To the right of this heading
are the Open All and Close All button that show a tooltip
on hover and focus. The three disclosure panels
are controlled by three toggles which are buttons embedded
inside <H4>
headings that also label the
toggled panels.
Cat Coat Patterns
Tuxedo cats refer to cats whose coats are a mix of only white and black, although there are dilute tuxedos who are gray and white. However, not all cats with black and white coats are "proper" tuxedos. A "true" tuxedo looks like they are in formal wear. They usually have a white belly that extends up to the next or face while the rest is black, just like a tuxedo shirt and coat. Quite often, they they will have more white on their face (including mustaches) as well as the very popular white socks at the end of their legs.
The calico cat is an amazing genetic circumstance that produces at tricolor cat of white, orange, and either gray or black. Because some coat colorings are sex-linked traits, it is extremely rare for a calico cat to be a male. In such cases, a male calico usually has some genetic anomalies such as being intersexed or having a chromosome duplication. The consequences are generally sterility but a beautiful coat.
A white cat is not necessarily albino, but there is a decent chance that the cat may have some degree of deafness. The degree of deafness is linked to eyecolor. White cats with blue eyes have a very high chance of being deaf, while other eye colors still have a higher chance of hearing issues compared to other cat coat patterns and colors.
HTML Structure
HTML Structure LinkThe general HTML structure of any stacked disclosure follows a fixed pattern that begins with the top matter followed by toggles and panels:
Stacked Disclosure HTML
<div role="region" class="stacked-disclosure" aria-labelledby="ID-STACK-NAME">
<div class="stack-top">
<h3 class="stack-name" id="ID-STACK-NAME"> ... </h3>
<button class="open-all">
<span>Open All</span>
<svg focusable="false"><use xlink:href="#icon-open-all"></use></svg>
</button>
<button class="close-all">
<span>Close All</span>
<svg focusable="false"><use xlink:href="#icon-close-all"></use></svg>
</button>
</div> <!-- end stack top -->
<h4 class="panel-toggle" data-disclosure-expanded="true / false">
<button class="toggle" aria-expanded="true / false">
<svg focusable="false" class="plus"><use xlink:href="#icon-plus"></use></svg>
<svg focusable="false" class="minus"><use xlink:href="#icon-minus"></use></svg>
<div class="toggle-text"> ... </div>
</button>
</h4> <!-- end panel toggle -->
<div class="panel">
...
</div> <!-- end panel -->
<!-- repeat panel-toggle and panel -->
<div> <!-- end stacked disclosure -->
Note that headings should be used in the stacked disclosure
for the .stack-name
and
the .panel-toggle
elements.
This benefits any users of assistive technologies. Note that
the headings should be properly nested. For example, if an
<h4>
is used for
the stack's name, the panel toggles need to be
<h5>
elements.
If you wish to use the open all, close all, plus, or minus SVG icons used in this demo, include the following SVG code on your page. Note that this code intentionally hides the SVG from screen readers, meaning that any use of the icons should provide proper accessible naming of where it is used.
SVG Icon HTML
<svg hidden aria-hidden="true" focusable="false" id="icons" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="icon-plus" viewBox="0 0 90 90">
<g>
<line stroke-width="20" stroke="currentColor" fill="none" y2="85" y1="5" x2="45" x1="45"/>
<line stroke-width="20" stroke="currentColor" fill="none" y2="45" y1="45" x2="85" x1="5"/>
</g>
</symbol>
<symbol id="icon-minus" viewBox="0 0 90 90">
<g>
<line stroke-width="20" stroke="currentColor" fill="none" y2="45" y1="45" x2="85" x1="5"/>
</g>
</symbol>
<symbol id="icon-close-all" viewBox="0 0 200 200">
<path stroke-width="10" stroke="currentColor" fill="transparent" style="fill: var(--top-fill-color, transparent); stroke: var(--top-stroke-color, currentColor)" d="M15 15h130v130H15z"/>
<path fill="none" stroke="currentColor" stroke-width="20" style="stroke: var(--icon-color, currentColor)" d="M40 80h80"/>
<path fill="none" stroke="currentColor" stroke-width="10" style="stroke: var(--stroke-color, currentColor)" d="M50 185h140M165 30v140"/>
<path fill="none" stroke="currentColor" stroke-width="10" style="stroke: var(--stroke-color, currentColor)" d="M30 165h140M185 50v135"/>
<g fill="none" stroke="transparent" style="stroke: var(--highlight-color, transparent)" stroke-width="10" >
<path d="M40 175h140M155 20v140M20 155h140M175 40v140"/>
</g>
</symbol>
<symbol id="icon-open-all" viewBox="0 0 200 200">
<path stroke-width="10" stroke="currentColor" fill="transparent" style="fill: var(--top-fill-color, transparent); stroke: var(--top-stroke-color, currentColor)" d="M15 15h130v130H15z"/>
<path fill="none" stroke="currentColor" stroke-width="20" style="stroke: var(--icon-color, currentColor)" d="M80 40v80M40 80h80"/>
<path fill="none" stroke="currentColor" stroke-width="10" style="stroke: var(--stroke-color, currentColor)" d="M50 185h140M165 30v140"/>
<path fill="none" stroke="currentColor" stroke-width="10" style="stroke: var(--stroke-color, currentColor)" d="M30 165h140M185 50v135"/>
<g fill="none" stroke="transparent" style="stroke: var(--highlight-color, transparent)" stroke-width="10" >
<path d="M40 175h140M155 20v140M20 155h140M175 40v140"/>
</g>
</symbol>
</svg>
Configuration Options
Configuration Options Link
Two configuration options are included with the stacked disclosures. The
first is the optional display of tooltips on the open all and close all
buttons. One can turn on the tooltips by including the tooltip
class on the stacked disclosure outer element:
<div role="region" class="stacked-disclosure tooltip" aria-labelledby="ID-STACK-NAME">
The other option involves including the Screen Reader Messaging JavaScript library on your page. If this library is optionally loaded, the open all and close all buttons will inform screen readers that the panels were successful all opened or closed. This is arguably an accessibility improvement as these buttons otherwise give no indication if any panels are open or closed.
Design Aspects
Design Aspects Accordion LinkDesign Specifications
Design Specifications LinkThe Stacked Disclosure pattern was created to meet the specific needs of a client to ensure that all accordions performed consistently on a site. The design request specified:
- Each accordion can have any number of panels opened or closed at any time independent of each other.
- The accordion has options to open or close all the panels at once.
- The overall accordion conforms and possibly exceeds accessibility standards.
Accessibility Features
Accessibility Features LinkAs accessibility was a key goal of the stacked disclosure pattern, multiple design decisions were made to ensure accessibility. These decisions were informed by the WAI-ARIA accordion example but modified to meet the design specifications and current browser capabilities.
-
The entire HTML intentionally uses semantic HTML properly. All interactive elements are
<button>
and thus come with the appropriate and expected built-in keyboard functionality.One exception to using semantic HTML was the decision to not use the native disclosure elements
<details>
and<summary>
. The<summary>
element cannot contain headings despite those being a recommended practice as that leads to the heading not being exposed to screen readers. This is a known ongoing access issue. As accordion toggles are recommended to be headings, this is the major reason why accordions should not rely on the<details>
element currently. - The toggle buttons for the panels utilize
aria-expanded="true / false"
to indicate to screen readers the state of each panel. -
The stacked disclosure is expected to use properly nested heading
elements for the
.stack-name
and the.panel-toggle
elements to make clear the overall structure of the disclosures. -
The overall stacked disclosure is marked as being a
role="region"
landmark. It is also named viaaria-labelledby
assigned to the.stack-name
.Marking individual panels as regions was also considered but decided against for the same reason articulated in the WAI-ARIA accordion pattern: overuse of landmark regions can lead to confusingly complex structures reported by screen readers.
- The Open All and Close All buttons have appropriate accessible names despite being represented only by icons. These names can optionally also be provided as tooltips if so desired. Usage of either button can also optionally provide feedback to screen readers via an ARIA live region if an additional library is loaded.
- For progressive enhancement purposes, the disclosure panels are set to open by default. If JavaScript is available, the panels are closed on page load. If mutation observers are available, the panels are closed as they are added to the DOM to prevent page flashing.