<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Inclusive Components]]></title><description><![CDATA[A blog trying to be a pattern library. All about designing inclusive web interfaces, piece by piece.]]></description><link>https://inclusive-components.design/</link><generator>Ghost 0.11</generator><lastBuildDate>Wed, 08 Nov 2017 05:42:57 GMT</lastBuildDate><atom:link href="https://inclusive-components.design/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Collapsible Sections]]></title><description><![CDATA[<p>Collapsible sections are perhaps the most rudimentary of interactive design patterns on the web. All they do is let you toggle the visibility of content by clicking that content's label. Big whoop.</p>

<p>Although the interaction is simple, it's an interaction that <a href="http://caniuse.com/#feat=details">does not have a consistent native implementation across browsers</a></p>]]></description><link>https://inclusive-components.design/collapsible-sections/</link><guid isPermaLink="false">db408a48-8f4e-4d9e-9bc0-60e2ba3cac31</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Thu, 26 Oct 2017 16:24:05 GMT</pubDate><content:encoded><![CDATA[<p>Collapsible sections are perhaps the most rudimentary of interactive design patterns on the web. All they do is let you toggle the visibility of content by clicking that content's label. Big whoop.</p>

<p>Although the interaction is simple, it's an interaction that <a href="http://caniuse.com/#feat=details">does not have a consistent native implementation across browsers</a> — despite movement to standardize it. It is therefore a great "hello world" entry point into accessible interaction design using JavaScript and WAI-ARIA.</p>

<p>So why am I talking about it now, after covering more complex components? Because this article will focus on developer and author experience: we're going to make our collapsible regions web components, so they are easy to include as part of larger patterns and in content files.</p>

<hr>

<p>As we did when approaching tab interfaces, it helps to consider what our component would be in the absence of JavaScript enhancement and why that enhancement actually makes things better. In this case, a collapsible section without JavaScript is simply a section. That is: a subheading introducing some content — prose, media, whatever.</p>

<pre><code>&lt;h2&gt;My section&lt;/h2&gt;  
&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras efficitur laoreet massa. Nam eu porta dolor. Vestibulum pulvinar lorem et nisl tempor lacinia.&lt;/p&gt;  
&lt;p&gt;Cras mi nisl, semper ut gravida sed, vulputate vel mauris. In dignissim aliquet fermentum. Donec arcu nunc, tempor sed nunc id, dapibus ornare dolor.&lt;/p&gt;  
</code></pre>

<p>One advantage of <em>collapsing</em> the content is that the headings become adjacent elements, giving the user an overview of the content available without having to scroll nearly so much. Expanding the content is choosing to see it.</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/compressed.svg" alt="Logform prose compressed into section headings/labels, leaving more space"></p>

<p>Another advantage is that keyboard users do not have to step through all of the focusable elements on the page to get to where they want to go: Hidden content is not focusable.</p>

<h2 id="theadaptedmarkup">The adapted markup</h2>

<p>Just attaching a click handler to the heading for the purposes of expanding the associated content is foolhardy, because it is not an interaction communicated to assistive software or achievable by keyboard. Instead, we need to adapt the markup by providing a standard button element.</p>

<pre><code>&lt;h2&gt;&lt;button&gt;My section&lt;/button&gt;&lt;/h2&gt;  
&lt;div&gt;  
  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras efficitur laoreet massa. Nam eu porta dolor. Vestibulum pulvinar lorem et nisl tempor lacinia.&lt;/p&gt;
  &lt;p&gt;Cras mi nisl, semper ut gravida sed, vulputate vel mauris. In dignissim aliquet fermentum. Donec arcu nunc, tempor sed nunc id, dapibus ornare dolor.&lt;/p&gt;
&lt;/div&gt;  
</code></pre>

<p>(<strong>Note:</strong> I have wrapped the content in a <code>&lt;div&gt;</code>, in preparation for showing and hiding it using the script to follow.)</p>

<p>The button is provided as a child of the heading. This means that, when a screen reader user focuses the <code>&lt;button&gt;</code>, the button itself is identified but also the presence of its parent: <em>"My section, button, heading level 2"</em> (or similar, depending on the screen reader).</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/announcement_1-1.svg" alt="Speech bubble above collapsible section label reads my section, button, heading level 2"></p>

<p>Had we instead <em>converted</em> the heading into a button using ARIA's <code>role="button"</code> we would be overriding the heading semantics. Screen reader users would lose the heading as a structural and navigational cue.</p>

<p>In addition, we would have to custom code all of the browser behaviors <code>&lt;button&gt;</code> gives us for free, such as focus (see <code>tabindex</code> in the example below) and key bindings to actually activate our custom control.</p>

<pre><code>&lt;!-- DON'T do this --&gt;  
&lt;h2 role="button" tabindex="0"&gt;My section&lt;/h2&gt;  
</code></pre>

<h3 id="state">State</h3>

<p>Our component can be in one of two mutually exclusive states: collapsed or expanded. This state can be suggested visually, but also needs to be communicated non-visually. We can do this by applying <code>aria-expanded</code> to the button, initially in the <code>false</code> (collapsed) state. Accordingly, we need to hide the associated <code>&lt;div&gt;</code> — in this case, with <code>hidden</code>.</p>

<pre><code>&lt;h2&gt;&lt;button aria-expanded="false"&gt;My section&lt;/button&gt;&lt;/h2&gt;  
&lt;div hidden&gt;  
  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras efficitur laoreet massa. Nam eu porta dolor. Vestibulum pulvinar lorem et nisl tempor lacinia.&lt;/p&gt;
  &lt;p&gt;Cras mi nisl, semper ut gravida sed, vulputate vel mauris. In dignissim aliquet fermentum. Donec arcu nunc, tempor sed nunc id, dapibus ornare dolor.&lt;/p&gt;
&lt;/div&gt;  
</code></pre>

<p>Some make the mistake of placing <code>aria-expanded</code> on the <em>target</em> element rather than the control itself. This is understandable since it is the content that actually switches state. But, if you think about it, this wouldn't be any good: the user would have to find the expanded content — which is only possible if it's actually expanded! — and then look around for an element that might control it. State is, therefore, communicated through the control that one uses to switch it.</p>

<div role="complementary">  
<h4>Is that all the button ARIA?</h4>  
<p>Why yes. We don't need to add <code>role="button"</code> because the <code>&lt;button></code> element implicitly has that role (the ARIA role is just for imitating the native role). And unlike <a href="https://inclusive-components.design/menus-menu-buttons/">menu buttons</a>, we are not instigating an immediate change of context by moving focus. Therefore, <code>aria-haspopup</code> is not applicable.</p>  
<p>Some folks add <code>aria-controls</code> and point it to the content container's <code>id</code>. Be warned that <a href="http://www.heydonworks.com/article/aria-controls-is-poop"><code>aria-controls</code> only works in JAWS</a> at the time of writing. So long as the section's content follows the heading/button in the source order, it isn't needed. The user will (immediately) encounter the expanded content as they move down the page.</p>  
</div>

<h3 id="stylingthebutton">Styling the button</h3>

<p>We've created a situation wherein we've employed a button, but a button that should look like an enhanced version of the heading it populates. The most efficient way to do this is to eradicate any user agent and author styles for buttons, forcing this button to inherit from its heading parent. </p>

<pre><code>h2 button {  
  all: inherit;    
}
</code></pre>

<p>Great, but now the button has no <a href="https://www.interaction-design.org/literature/book/the-glossary-of-human-computer-interaction/affordances">affordance</a>. It doesn't look like it can be activated. This is where, conventionally, a plus/minus symbol is incorporated. Plus indicates that the section can be expanded, and minus that it may be collapsed.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/10/expanded_collapsed.svg" alt="The first illustration shows a plus sign and the speech bubble reads My section, button collapsed. The second illustration shows a minus sign and the bubble reads button expanded.">
<figcaption>The text label and/or icon for a button should always show what pressing that button <em>will</em> do,  
 hence the minus sign in the expanded state indicating that the button will take the section content away.
</figcaption>  
</figure>

<p>The question is: how do we render the icon? The answer: as efficiently and accessibly as possible. Simple shapes such as rectangles (<code>&lt;rect&gt;</code>) are a highly efficient way to create icons with SVG, so let's do that.</p>

<pre><code>&lt;svg viewBox="0 0 10 10"&gt;  
  &lt;rect height="8" width="2" y="1" x="4"/&gt;
  &lt;rect height="2" width="8" y="4" x="1"/&gt;
&lt;/svg&gt;  
</code></pre>

<p>There, that's small enough to fit in a tweet. Since state is communicated via the <code>aria-expanded</code> attribute non-visually, we don't need this graphic to be screen reader accessible or interactive. In which case, we need to add a couple more attributes.</p>

<pre><code>&lt;button aria-expanded="false"&gt;  
  My section
  &lt;svg viewBox="0 0 10 10" aria-hidden="true" focusable="false"&gt;
    &lt;rect class="vert" height="8" width="2" y="1" x="4" /&gt;
    &lt;rect height="2" width="8" y="4" x="1" /&gt;
  &lt;/svg&gt;
&lt;/button&gt;  
</code></pre>

<ul>
<li><code>aria-hidden="true"</code> hides the SVG from screen readers and other assistive technologies</li>
<li><code>focusable="false"</code> addresses the issue that Internet Explorer/Edge make SVGs focusable by default</li>
</ul>

<p>Note the class of "vert" for the rectangle that represents the vertical strut. We're going to target this with CSS to show and hide it depending on the state, transforming the icon between a plus and minus shape.</p>

<pre><code>[aria-expanded="true"] .vert {
  display: none;
}
</code></pre>

<p>Tying state and its visual representation together is <em>a very good thing</em>. It ensures that state changes are communicated interoperably. Do not listen to those who advocate the absolute separation of HTML semantics and CSS styles. Form should follow function, and <em>directly</em> is most reliable.</p>

<p>Note that the default focus style was removed with <code>inherit: all</code>. We can delegate a focus style to the SVG with the following. </p>

<pre><code>h2 button:focus svg {  
  outline: 2px solid;
}
</code></pre>

<h4 id="highcontrastthemes">High contrast themes</h4>

<p>One more thing: We can ensure the <code>&lt;rect&gt;</code> elements respect high contrast themes. By applying a <code>fill</code> of <code>currentColor</code> to the <code>&lt;rect&gt;</code> elements, they change color with the surrounding text when it is affected by the theme change.</p>

<pre><code>[aria-expanded] rect {
  fill: currentColor;
}
</code></pre>

<p>To test high contrast themes against your design on Windows, search for <strong>High contrast settings</strong> and apply a theme from <strong>Choose a theme</strong>. Many high contrast themes invert colors to reduce light intensity. This helps folks who suffer migraines or photophobia as well as making elements clearer to those with vision impairments.</p>

<div role="complementary">  
<h4>Why not use <code>&lt;use></code>?</h4>  
<p>If we had many collapsible regions on the page, reusing the same SVG <code>&lt;pattern></code> definition via <a href="https://wearejh.com/inline-svg-use-element/"><code>&lt;use></code> elements</a> and <code>xlink:href</code> would reduce redundancy.</p>



<pre><code>&lt;button aria-expanded="false">
  My section
  &lt;svg viewBox="0 0 10 10 aria-hidden="true" focusable="false">
    &lt;use xlink:href="#plusminus"/&gt;
  &lt;/svg>
&lt;/button>
</code></pre>
<p>Unfortunately, this would mean we could no longer target the specific <code>.vert</code> rectangle to show and hide it. By using little code to define each identical SVG, this is not a big problem in our case.</p>  
</div>

<h3 id="asmallscript">A small script</h3>

<p>Given the simplicity of the interaction and all the elements and semantics being in place, we need only write a very terse script:</p>

<pre><code>(function() {
  const headings = document.querySelectorAll('h2')

  Array.prototype.forEach.call(headings, heading =&gt; {
    let btn = heading.querySelector('button')
    let target = heading.nextElementSibling

    btn.onclick = () =&gt; {
      let expanded = btn.getAttribute('aria-expanded') === 'true' || false

      btn.setAttribute('aria-expanded', !expanded)
      target.hidden = expanded    
    }
  })
})()
</code></pre>

<p>Here's an accompanying <a href="https://codepen.io/heydon/pen/QqzRvQ/">CodePen demo</a>:</p>

<iframe height="265" scrolling="no" title="Collapsible sections" src="//codepen.io/heydon/embed/QqzRvQ/?height=265&theme-id=0&default-tab=js,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/QqzRvQ/">Collapsible sections</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h3 id="progressiveenhancement">Progressive enhancement</h3>

<p>The trouble with the above script is that it requires the HTML to be adapted manually for the collapsible sections to work. Implemented by an engineer as a component via a template/JSX, this is expected. However, for largely static sites like blogs there are two avoidable issues: </p>

<ul>
<li>If JavaScript is unavailable, there are interactive elements in the DOM that don't do anything, with semantics that therefore make no sense.</li>
<li>The onus is on the author/editor to construct the complex HTML. </li>
</ul>

<p>Instead, we can take basic prose input (say, written in markdown or in a WYSIWYG) and enhance it <em>after the fact</em> with the script. This is quite trivial in jQuery given the <code>nextUntil</code> and <code>wrapAll</code> methods, but in plain JavaScript we need to do some iteration. Here's another CodePen that automatically adds the toggle button and groups the section content for toggling. It targets all <code>&lt;h2&gt;</code>s found in the <code>&lt;main&gt;</code> part of the page.</p>

<iframe height="265" scrolling="no" title="Collapsible sections PE" src="//codepen.io/heydon/embed/gGNaoM/?height=265&theme-id=0&default-tab=js,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/gGNaoM/">Collapsible sections PE</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<p>Why write it in plain JavaScript? Because modern browsers support Web API methods very consistently now, and because small interactions should not depend on large libraries.</p>

<h2 id="aprogressivewebcomponent">A progressive web component</h2>

<p>The last example meant we didn't have to think about our collapsible sections during editorial; they'd just appear automatically. But what we gained in convenience, we lost in control. Instead, what if there was a compromise wherein there was very little markup to write, but what we <em>did</em> write let us choose which sections should be collapsible and what state they should be in on page load? </p>

<p>Web components could be the answer. Consider the following:</p>

<pre><code>&lt;toggle-section open="false"&gt;  
  &lt;h2&gt;My section&lt;/h2&gt;
  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras efficitur laoreet massa. Nam eu porta dolor. Vestibulum pulvinar lorem et nisl tempor lacinia.&lt;/p&gt;
  &lt;p&gt;Cras mi nisl, semper ut gravida sed, vulputate vel mauris. In dignissim aliquet fermentum. Donec arcu nunc, tempor sed nunc id, dapibus ornare dolor.&lt;/p&gt;
&lt;/toggle-section&gt;  
</code></pre>

<p>The custom element name is easy to remember, and the <code>open</code> attribute has obvious implications. Better still, where JavaScript is unavailable, this outer element is treated like a mere <code>&lt;div&gt;</code> and the collapsible section remains a simple section. No real harm done.</p>

<p>In fact, if we detect support for the <code>&lt;template&gt;</code> element and <code>attachShadow</code> within our script, the same fallback will be presented to browsers not supporting these features.</p>

<pre><code>if ('content' in document.createElement('template')) {  
  // Define the &lt;template&gt; for the web component

  if (document.head.attachShadow) {
    // Define the web component using the v1 syntax
  }
}
</code></pre>

<h3 id="thetemplate">The template</h3>

<p>We could place a template element in the markup and reference it, or create one on the fly. I'm going to do the later.</p>

<pre><code>tmpl.innerHTML = `  
  &lt;h2&gt;
    &lt;button aria-expanded="false"&gt;
      &lt;svg aria-hidden="true" focusable="false" viewBox="0 0 10 10"&gt;
        &lt;rect class="vert" height="8" width="2" y="1" x="4"/&gt;
        &lt;rect height="2" width="8" y="4" x="1"/&gt;
      &lt;/svg&gt;
    &lt;/button&gt;
  &lt;/h2&gt;
  &lt;div class="content" hidden&gt;
    &lt;slot&gt;&lt;/slot&gt;
  &lt;/div&gt;
  &lt;style&gt;
    h2 {
      margin: 0;
    }

    h2 button {
      all: inherit;
      box-sizing: border-box;
      display: flex;
      justify-content: space-between;
      width: 100%;
      padding: 0.5em 0;
     }

    button svg {
      height: 1em;
      margin-left: 0.5em;
    }

    [aria-expanded="true"] .vert {
      display: none;
    }

    [aria-expanded] rect {
      fill: currentColor;
    }
  &lt;/style&gt;
`
</code></pre>

<p>This template content will become the Shadow DOM subtree for the component. </p>

<p>By styling the collapsible section from <em>within</em> its own Shadow DOM, the styles do not affect elements in Light DOM (the standard, outer DOM). Not only that, but they are not applied unless the browser supports <code>&lt;template&gt;</code> and custom elements.</p>

<h3 id="definingthecomponent">Defining the component</h3>

<p>Note the <code>&lt;slot&gt;</code> element in the template HTML, which is a window to our Light DOM. This makes it much easier to wrap the content provided by the author than in the <a href="https://codepen.io/heydon/pen/gGNaoM">previous progressive enhancement demo</a>.</p>

<p>Inside the component definition, <code>this.innerHTML</code> refers to this Light DOM content. We shall create a <code>shadowRoot</code> and populate it with the template's content. The Shadow DOM markup is instead found with <code>this.shadowRoot.innerHTML</code>.</p>

<pre><code>class ToggleSection extends HTMLElement {  
  constructor() {
    super()

    this.attachShadow({ mode: 'open' })
    this.shadowRoot.appendChild(tmpl.content.cloneNode(true))
  }
}
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/10/flow.svg" alt="Diagram showing how the working web component is constructed from static content and a template into a combination of shadow and light DOM."></p>

<p>With these references, we can move Light DOM to Shadow DOM. Which means we can repurpose the Light DOM <code>&lt;h2&gt;</code>'s label and eliminate the now superfluous element. It probably seems dirty doing this DOM manipulation — especially when you're used to simple, declarative (React) components. But it's what makes the web component progressive.</p>

<pre><code>this.btn = this.shadowRoot.querySelector('h2 button')  
var oldHeading = this.querySelector('h2')  
var label = oldHeading.textContent  
this.btn.innerHTML = label + this.btn.innerHTML  
oldHeading.parentNode.removeChild(oldHeading)  
</code></pre>

<p>Actually, we can do one better and support different introductory heading levels. Instead of targeting headings at all, we can just get the first element in the Light DOM. Making sure the first element is a heading would be a matter for editorial guidance. However, if it's not a heading, we can make good of any element — as I shall demonstrate.</p>

<pre><code>var oldHeading = this.querySelector(':first-child')  
</code></pre>

<p>Now we just need to make sure the <em>level</em> for the Shadow DOM heading is faithful to the Light DOM original. I can query the <code>tagName</code> of the Light DOM heading and augment the Shadow DOM level with <code>aria-level</code> accordingly.</p>

<pre><code>let level = parseInt(oldHeading.tagName.substr(1))  
this.heading = this.shadowRoot.querySelector('h2')  
if (level &amp;&amp; level !== 2) {  
  this.heading.setAttribute('aria-level', level)
}
</code></pre>

<p>The second character of <code>tagName</code> is parsed as an integer. If this is a true integer (<code>NaN</code> is falsey) and isn't the <code>2</code> offered implicitly by <code>&lt;h2&gt;</code>, <code>aria-level</code> is applied. As a fallback, a non-heading element still gives up its <code>textContent</code> as the label for the extant Shadow DOM <code>&lt;h2&gt;</code>. This can be accompanied by a polite <code>console.warn</code>, advising developers to use a heading element as a preference.</p>

<pre><code>if (!level) {  
  console.warn('The first element inside each &lt;toggle-section&gt; should be a heading of an appropriate level.')
}
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/10/warn.png" alt="The warning message, reading " the="" first="" element="" inside="" each="" toggle="" section="" should="" be="" a="" heading="" of="" an="" appropriate="" level"="" as="" seen="" in="" browser="" console."=""></p>

<p>One advantage of using <code>aria-level</code> is that, in our case, it is not being used as a styling hook — so the appearance of the heading/button remains unchanged.</p>

<pre><code>&lt;h2 aria-level="3"&gt;  
  &lt;button aria-expanded="false"&gt;
    &lt;svg aria-hidden="true" focusable="false" viewBox="0 0 10 10"&gt;
      &lt;rect class="vert" height="8" width="2" y="1" x="4"/&gt;
      &lt;rect height="2" width="8" y="4" x="1"/&gt;
    &lt;/svg&gt;
  &lt;/button&gt;
&lt;/h2&gt;  
</code></pre>

<p>If you wanted your collapsible section headings to reflect their level, you could include something like the following in your CSS.</p>

<pre><code>toggle-section [aria-level="2"] {  
  font-size: 2rem;
}

toggle-section [aria-level="3"] {  
  font-size: 1.5rem;
}

/* etc */
</code></pre>

<h4 id="theregionrole">The region role</h4>

<p>Any content that is introduced by a heading is a <em>de facto</em> (sub)section within the page. But, as I covered in <a href="https://inclusive-components.design/a-todo-list/#headinglevel"><strong>A Todo List</strong></a>, you can create explicit sectional container elements in the form of <code>&lt;section&gt;</code>. You get the same effect by applying <code>role="region"</code> to an element, such as our custom <code>&lt;toggle-section&gt;</code> (which otherwise offers no such accessible semantics).</p>

<pre><code>&lt;toggle-section role="region"&gt;  
  ...
&lt;/toggle-section&gt;  
</code></pre>

<p>Screen reader users are <a href="http://www.heydonworks.com/article/responses-to-the-screen-reader-strategy-survey">more likely to traverse a document by heading than region</a> but many screen readers <em>do</em> provide region shortcuts. Adding <code>role="region"</code> gives us quite a bit:</p>

<ul>
<li>It provides a fallback navigation cue for screen reader users where the Light DOM does not include a heading.</li>
<li>It elicits the announcement of "region" when the screen reader user enters that section, which acts as a structural cue.</li>
<li>It gives us a styling hook in the form <code>toggle-button[role="region"]</code>. This lets us add styles we only want to see if the script has run and web components are supported.</li>
</ul>

<h3 id="tetheringopenandariaexpanded">Tethering <code>open</code> and <code>aria-expanded</code></h3>

<p>When the component's <code>open</code> value changes between <code>true</code> and <code>false</code> we want the appearance of the content to toggle. By harnessing <code>observedAttributes()</code> and <code>attributeChangedCallback()</code> we can do this <em>directly</em>. We place this code after the component's constructor:</p>

<pre><code>static get observedAttributes() {  
  return ['open']
}

attributeChangedCallback(name) {  
  if (name === 'open') {
    this.switchState()
  }
}
</code></pre>

<ul>
<li><code>observedAttributes()</code> takes an array of all the attributes on the parent <code>&lt;toggle-section&gt;</code> that we wish to watch</li>
<li><code>attributeChangedCallback(name)</code> lets us execute our <code>switchState()</code> function in the event of a change to <code>open</code></li>
</ul>

<p>The advantage here is that we can toggle state using a script that simply changes the <code>open</code> value, from outside the component. For <em>users</em> to change the state, we can just flip <code>open</code> inside a click function:</p>

<pre><code>this.btn.onclick = () =&gt; {  
  this.setAttribute('open', this.getAttribute('open') === 'true' ? 'false' : 'true')
}
</code></pre>

<p>Since the <code>switchState()</code> function augments the <code>aria-expanded</code> value, we have tethered <code>open</code> to <code>aria-expanded</code>, making sure the state change is accessible.</p>

<pre><code>this.switchState = () =&gt; {  
  let expanded = this.getAttribute('open') === 'true' || false
  this.btn.setAttribute('aria-expanded', expanded)
  this.shadowRoot.querySelector('.content').hidden = !expanded
}
</code></pre>

<p>Here's the <a href="https://codepen.io/heydon/pen/ZXdbxj/">CodePen for this version of the web component</a> with comments:</p>

<iframe height="265" scrolling="no" title="Collapsible section web component" src="//codepen.io/heydon/embed/ZXdbxj/?height=265&theme-id=0&default-tab=js,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/ZXdbxj/">Collapsible section web component</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h3 id="expandcollapseall">Expand/collapse all</h3>

<p>Since we toggle <code>&lt;toggle-section&gt;</code> elements via their <code>open</code> attribute, it's trivial to afford users an 'expand/collapse all' behavior. One advantage of such a provision is that users who have opened multiple sections independently can 'reset' to an initial, compact state for a better overview of the content. By the same token, users who find fiddling with interactive elements distracting or tiresome can revert to scrolling through open sections.</p>

<p>It's tempting to implement 'expand/collapse all' as a single toggle button. But we don't know how many sections will initially be in either state. Nor do we know, at any given time, how many sections the user has opened or closed manually.</p>

<p>Instead, we should group two alternative controls.</p>

<pre><code>&lt;ul class="controls" aria-label="section controls"&gt;  
  &lt;li&gt;&lt;button id="expand"&gt;expand all&lt;/button&gt;&lt;/li&gt;
  &lt;li&gt;&lt;button id="collapse"&gt;collapse all&lt;/button&gt;&lt;/li&gt;
&lt;/ul&gt;  
</code></pre>

<p>It's important to group related controls together, and lists are the standard markup for doing so. See also: the lists of navigation links discussed in <a href="https://inclusive-components.design/menus-menu-buttons/"><strong>Menus &amp; Menu Buttons</strong></a>. Lists and list items tell screen reader users when they are interacting with related elements and how many of these elements there are. </p>

<p>Some compound ARIA widgets have their own grouping mechanisms, like <code>role="menu"</code> grouping <code>role="menuitem"</code> elements or <code>role="tablist"</code> grouping <code>role="tab"</code> elements. Our use case does not suit either of these paradigms, and a simple labeled list suffices.</p>

<p>Because <code>&lt;ul&gt;</code> is implicitly a 'group' element, many assistive technologies will acknowledge a group label provided to it using <code>aria-label</code>. In VoiceOver, when a user enters the list and focuses the button, they will hear <em>"expand all, button, list, section controls, two items"</em>.</p>

<p>Note that using <code>aria-label</code> only provides a non-visual label. This is acceptable if the purpose of the buttons can be gleaned visually through other cues such as layout. In this case, the proximity of the buttons to the sections probably suffices, but testing should be undertaken.</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/section_controls.svg" alt="Diagram shows that the two buttons are are grouped under the label, section controls."></p>

<h3 id="trackingtheurl">Tracking the URL</h3>

<p>One final refinement.</p>

<p>Conventionally, and in the absence of JavaScript enhancement, users are able to follow and share links to specific page sections by their <code>hash</code>. This is expected, and part of the generic UX of the web. </p>

<p>Most parsers add <code>id</code> attributes for this purpose to heading elements. As the heading element for a target section in our enhanced interface may be inside a collapsed/unfocusable section, we need to open that to reveal the content and move focus to it. The <code>connectedCallback()</code> lifecycle lets us do this when the component is ready. It's like <code>DOMContentLoaded</code> but for web components.</p>

<pre><code>connectedCallback() {  
  if (window.location.hash.substr(1) === this.heading.id) {
    this.setAttribute('open', 'true')
    this.btn.focus()
  } 
}
</code></pre>

<p>Note that we focus the button inside the component's heading. This takes keyboard users to the pertinent component ready for interaction. In screen readers, the parent heading level will be announced along with the button label.</p>

<p>Further to this, we should be updating the <code>hash</code> each time the user opens successive sections. Then they can share the specific URL without needing to dig into dev tools (if they know how!) to copy/paste the heading's <code>id</code>. Let's use <code>pushState</code> to dynamically change the URL without reloading the page:</p>

<pre><code>this.btn.onclick = () =&gt; {  
  let open = this.getAttribute('open') === 'true' || false
  this.setAttribute('open', open ? 'false' : 'true')

  if (this.heading.id &amp;&amp; !open) {
    history.pushState(null, null, '#' + this.heading.id)
  }
}
</code></pre>

<p>Here's <a href="https://codepen.io/heydon/pen/ZXgqKG">a demo with the <code>hash</code> tracking capability added</a>:</p>

<iframe height="265" scrolling="no" title="Collapsible section web component /w hashes" src="//codepen.io/heydon/embed/ZXgqKG/?height=265&theme-id=0&default-tab=js,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/ZXgqKG/">Collapsible section web component /w hashes</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h2 id="conclusion">Conclusion</h2>

<p>Your role as an interface designer and developer (yes, you can be both at the same time) is to serve the needs of the people receiving your content and using your functionality. These needs encompass both those of 'end users' and fellow contributors. The product should of course be accessible and performant, but maintaining and expanding the product should be possible without esoteric technical knowledge.</p>

<p>Whether implemented through web components or not, progressive enhancement not only ensures the interface is well-structured and robust. As we've seen here, it can also simplify the editorial process. This makes developing the application and its content more inclusive. </p>

<h3 id="checklist">Checklist</h3>

<ul>
<li>Don't depend on large libraries for small interactions, unless the library in question is likely to be used for multiple other interactive enhancements.</li>
<li>Do not override important element roles. See <a href="https://www.w3.org/TR/using-aria/#second">the second rule of ARIA use</a>.</li>
<li>Support high contrast themes in your SVG icons with <code>currentColor</code>.</li>
<li>If the content is already otherwise static, there is a good case for basing your web component on progressive enhancement.</li>
<li>Do please come up with more descriptive labels for your sections than "Section 1", "Section 2" etc. Those are just placeholders!</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Tabbed Interfaces]]></title><description><![CDATA[<p>When you think about it, most of your basic interactions are showing or hiding something <em>somehow</em>. I've already covered <a href="https://inclusive-components.design/menus-menu-buttons/">popup menu buttons</a> and the simpler and less assuming <a href="https://inclusive-components.design/tooltips-toggletips/">tooltips and toggletips</a>. You can add simple disclosure widgets, compound "accordions", and their sister component the <strong>tabbed interface</strong> to that list. It's</p>]]></description><link>https://inclusive-components.design/tabbed-interfaces/</link><guid isPermaLink="false">dabb140b-8076-4c8c-9664-49e3f9142e1a</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Thu, 05 Oct 2017 12:26:45 GMT</pubDate><content:encoded><![CDATA[<p>When you think about it, most of your basic interactions are showing or hiding something <em>somehow</em>. I've already covered <a href="https://inclusive-components.design/menus-menu-buttons/">popup menu buttons</a> and the simpler and less assuming <a href="https://inclusive-components.design/tooltips-toggletips/">tooltips and toggletips</a>. You can add simple disclosure widgets, compound "accordions", and their sister component the <strong>tabbed interface</strong> to that list. It's also worth noting that routed single-page applications emulate the showing and hiding of entire web pages using JavaScript.</p>

<p>As we shall explore, the conceptual boundaries between tab panels, application views, and simple document fragments are not as clearly defined as we might like to pretend. Nonetheless, we need to assert with confidence precisely what kind of interface we are providing the user, otherwise they won't find the confidence to successfully operate it.</p>

<hr>

<p>Proponents of progressive enhancement conceive interfaces in terms of structured static content before contemplating how those interfaces may become enhanced with additional JavaScript-enabled interactivity. Even if you are happy to concede a JavaScript dependency early in an interface's design, it's beneficial to build a robust foundation using semantic HTML, capitalizing on standard browser behaviors. Sometimes you may even find JavaScript enhancement is a step you needn't take.</p>

<p>For my money, an embryonic tabbed interface is just <a href="https://inclusive-components.design/menus-menu-buttons/#tablesofcontent">a table of content with same-page links</a> pointing at different sections of the page. Both a table of content and a list of tabs allow the user to choose between distinct sections of content.</p>

<ul>
<li>Table of contents → tab list</li>
<li>Same-page links → tabs</li>
<li>Sections → tab panels</li>
</ul>

<p><img src="https://inclusive-components.design/content/images/2017/10/toc_and_tabs.png" alt="On the left: a table of content atop some headed page sections. On the right: a tab interface with the first tab selected."></p>

<h2 id="cssenhancement">CSS enhancement</h2>

<p>What if I used some CSS to make just the chosen section from my table of contents visible? This is certainly possible using the <code>:target</code> pseudo-class.</p>

<pre><code>section:not(:target) {  
  display: none;
}
</code></pre>

<iframe height="265" scrolling="no" title="TOC with :target" src="//codepen.io/heydon/embed/VMMrgN/?height=265&theme-id=0&default-tab=result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/VMMrgN/">TOC with :target</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<p>By placing the disclosure of content under the user's control, our CSS-enhanced TOC interface moves towards being a tabbed interface in one critical regard. Since <code>display: none</code> hides content from assistive technologies, this enhancement affects screen reader users as much as anyone else. </p>

<p>Take the TOC links and align them horizontally, then this little CSS experiment begins to really look like a tabbed interface. But herein lies a problem.</p>

<p>In <a href="https://resilientwebdesign.com/chapter2/">Chapter 2 of his book, Resilient Web Design</a> Jeremy Keith talks about <em>material honesty</em>; that "one material should not be used as a substitute for another." In this case, we'd be making a table of contents <em>appear</em> like a tab list. We should avoid this since users who <em>see</em> tabs expect certain behaviors not offered by a simple list of links.</p>

<p>It is for the same reason that a tabbed design should not be employed for site-wide navigation. At the very least, when a user selects a "tab" they would not expect to be navigated to an entirely new page!</p>

<p>I have encountered innumerable JavaScript-driven and ARIA-adorned, fully-fledged tabbed interfaces where simple tables of content atop page sections would have done just as well. Better even, since they are more robust and efficient. But for goodness' sake make them <em>look</em> like tables of content. Meet the expectations you set in visual design with your semantics and behaviors.</p>

<h2 id="truetabbedinterfaces">True tabbed interfaces</h2>

<p>The advantage of using lists of same-page links and the standard browser behaviors they invoke is that they are simple and easy to understand — especially since the behavior of links is peculiar to the web.</p>

<p>Tabbed interfaces, on the other hand, are a paradigm imported from desktop applications. If they are understood by users in the context of web pages <em>at all</em> it is only through very careful and deliberate exposition of visual design and ARIA semantics.</p>

<p>What makes a tabbed interface a tabbed interface is in the ergonomics of its keyboard behavior. Really the only reason the ARIA semantics need be present is to alert screen reader users to the keyboard behaviors they should expect. Here is the basic semantic structure with notes to follow:</p>

<pre><code>&lt;ul role="tablist"&gt;  
  &lt;li role="presentation"&gt;
    &lt;a role="tab" href="#section1" id="tab1" aria-selected="true"&gt;Section 1&lt;/a&gt;
  &lt;/li&gt;
  &lt;li role="presentation"&gt;
    &lt;a role="tab" href="#section2" id="tab2"&gt;Section 2&lt;/a&gt;
  &lt;/li&gt;
  &lt;li role="presentation"&gt;
     &lt;a role="tab" href="#section3" id="tab3"&gt;Section 3&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;  
&lt;section role="tabpanel" id="section1" aria-labelledby="tab1"&gt;  
  ...
&lt;/section&gt;  
&lt;section role="tabpanel" id="section2" aria-labelledby="tab2" hidden&gt;  
  ...
&lt;/section&gt;  
&lt;section role="tabpanel" id="section3" aria-labelledby="tab3" hidden&gt;  
  ...
&lt;/section&gt;  
</code></pre>

<ul>
<li>This tabbed interface is progressively enhanced from a table of content and corresponding document sections. In some cases this means adding (<code>aria-selected</code>) or overriding (<code>role="tab"</code>) semantics. In others (<code>role="presentation"</code>) it means removing semantics that are no longer applicable or helpful. You don't want a set of tabs to also be announced as a plain list.</li>
<li><code>role="tablist"</code> does not delegate semantics to its children automatically. It must be used in conjunction with individual <code>tab</code> roles in order for tabs to be identified and enumerated in assistive technologies.</li>
<li>The <code>tabpanel</code> elements which do not correspond to the selected tab are hidden using the <code>hidden</code> attribute/property.</li>
<li>Users who enter a tabpanel should be assured of its identity. Hence, <code>aria-labelledby</code> is used to label the panel via the tab name. In practice, this means a screen reader user entering a panel and focusing a link will hear something like <em>"Section 1 tab panel, [link label] link"</em>.</li>
</ul>

<h3 id="keyboardbehavior">Keyboard behavior</h3>

<p>Unlike a same-page link, a tab does not move the user to the associated section/panel of content. It just reveals the content visually. This is advantageous to sighted users (including sighted screen reader users) who wish to flit between different sections without having to wade back up the page each time they want to choose a new one.</p>

<p>This comes with an unfortunate side effect: If the user wishes to move <em>to</em> a section by keyboard and interact with its internal content, they have to step through any tabs to the right of the current tab, which are in focus order.</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/tab_order_wrong_small-1.png" alt="Shows the path a keyboard user would take from the active tab, through the inactive tabs to the content."></p>

<p>This problem is solved by delegating tab selection to arrow keys. The user is able to select and activate tabs using the arrow keys, while the <kbd>Tab</kbd> key is preserved for focusing contents within and below the active tab panel. To put it another way: <kbd>Tab</kbd> is not for tabs, which I concede is a bit confusing. I wish the key and the control had different names, but alas.</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/tab_order_right_small-1.png" alt="Shows how a user can choose a new tab with the arrow keys or press tab to enter the tab panel and focus a link"></p>

<p>It's equally important that pressing <kbd>Shift</kbd> + <kbd>Tab</kbd> returns the user to the selected tab. This is all possible by giving each tab but the selected tab <code>tabindex="-1"</code>, which removes the inactive tabs from focus order but allows focus via a script. In the following example, the second tab is the selected tab, as denoted by the <code>aria-selected</code> state being set to true.</p>

<pre><code>&lt;ul role="tablist"&gt;  
  &lt;li role="presentation"&gt;
    &lt;a role="tab" tabindex="-1" href="#section1"&gt;Section 1&lt;/a&gt;
  &lt;/li&gt;
  &lt;li role="presentation"&gt;
    &lt;a role="tab" href="#section2" aria-selected="true"&gt;Section 2&lt;/a&gt;
  &lt;/li&gt;
  &lt;li role="presentation"&gt;
     &lt;a role="tab" tabindex="-1" href="#section2"&gt;Section 3&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;  
</code></pre>

<p>With <code>tabindex="-1"</code> in place for the remaining tabs, I can capture the <code>keydown</code> event for the left or right arrow keys to make the desired inactive tab active.</p>

<pre><code>tab.addEventListener('keydown', e =&gt; {  
  let dir = e.which === 37 ? 'left' : 39 ? 'right' : null;
  if (dir) {
    switchTab(e.eventTarget, dir);
  }  
})
</code></pre>

<p>Each time a user selects a new tab, the corresponding tab panel is revealed. When the second of four tabs is selected, any screen reader running will say something similar to <em>"[tab label], selected, tab, 2 of 4"</em>. Plentiful information.</p>

<h4 id="aproblemreadingpanels">A problem reading panels</h4>

<p>Now that pressing <kbd>Tab</kbd> bypasses the tabs, it's trivial for keyboard users to move focus to the first of any links or other interactive elements in the open panel.</p>

<p>The experience for screen reader users is not currently as optimal. Although they too can focus elements inside the panel directly from the selected tab, blind users cannot see any content that comes before or after that interactivity. If there is no interactive content in the panel at all, they will unwittingly focus the first interactive element <em>outside</em> and below the tab interface.</p>

<p>In the operation of screen readers like NVDA and JAWS, <a href="https://webaim.org/resources/shortcuts/nvda#reading">the down arrow moves the user to the next element</a> (focusable or otherwise) and reads it out. Without intervention, this would be the next tab in the <code>tablist</code>. Instead, we can intercept the down arrow key press and move focus programmatically to the open panel itself, making sure it isn't missed. See <code>panels[i].focus()</code> in the following snippet:</p>

<pre><code>tab.addEventListener('keydown', e =&gt; {  
  let index = Array.prototype.indexOf.call(tabs, e.currentTarget);
  let dir = e.which === 37 ? index - 1 : e.which === 39 ? index + 1 : e.which === 40 ? 'down' : null;
  if (dir !== null) {
    e.preventDefault();
    dir === 'down' ? panels[i].focus() : tabs[dir] ? switchTab(e.currentTarget, tabs[dir]) : void 0;
  }
});
</code></pre>

<p>The <code>void 0</code> part means "do nothing" for the case that the adjacent tab does not exist (because you're already at the start or end of the <code>tablist</code>). You can see the full script in <a href="https://codepen.io/heydon/pen/veeaEa/">the CodePen demo</a>.</p>

<p>Since tab panels are labeled by their tabs, when the down arrow is pressed and the relevant tab panel focused, a screen reader will announce, <em>"[tab label], tab panel"</em>, thereby assuring the user of their new location within the interface. From there, they can continue to browse down through the tab panel's descendant elements or press <kbd>Shift</kbd> + <kbd>Tab</kbd> to return to the <code>tablist</code> and the selected tab.</p>

<p>Although sighted keyboard users are less likely to use the down arrow key, it's important the focused tab panel has a focus style to indicate a change of focus location. This focusable panel provision does not impede operation for sighted keyboard users, who can do everything they need with just the <kbd>Tab</kbd> and left and right arrow keys.</p>

<div role="complementary">  
<h4>The focus of non-interactive elements</h4>  
<p>In this implementation we are technically making a non-interactive element focusable by the user, albeit via an atypical key.</p>  
<p>The general rule is not to allow the focus of non-interactive elements by the user because the expectation is that focusable elements will each actually <em>do</em> something. Accordingly, code like the following would fail WCAG's <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-order.html"><strong>2.4.3 Focus Order</strong></a> success criterion. It offers an unusable element to be used.</p>  


<pre><code>&lt;h2 tabindex="0">Section 3&lt;h2></code></pre>
<p>However, directing focus to an element using a script is acceptable where the user has <em>chosen</em> that change of context. In some single-page application implementations, when a user chooses a new "view", the newly constructed view element or its main heading is focused.</p>  


<pre><code>&lt;h2 tabindex="-1">Application View&lt;h2></code></pre>
<p>Focusing the heading will announce the heading content,  
 which doubles as the view's label. This lets screen reader users know about their change of context. Note the use of <code>tabindex="-1"</code>. As with our arrow key-controlled tabs, this allows focus by script but not directly by the user (unless a custom key is assigned). In practice, it lets us move focus without adding the focused element to the user's tab order — as <code>tabindex="0"</code> would.</p>
</div>

<p>Here is <a href="https://codepen.io/heydon/pen/veeaEa/">a codePen of the tab interface</a>, written in native JavaScript and with the behaviors and semantics discussed. It is progressively enhanced from a list of links and <code>&lt;section&gt;</code> elements and is 1.3KB minified as ES5:</p>

<iframe height="265" scrolling="no" title="Tab Interface (PE)" src="//codepen.io/heydon/embed/veeaEa/?height=265&theme-id=0&default-tab=result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/veeaEa/">Tab Interface (PE)</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h3 id="responsivedesign">Responsive design</h3>

<p>Responsive design is inclusive design. Not only is a responsive design compatible with a maximal number of devices, but it's also sensitive to a user's zoom settings. Full-page zoom triggers <code>@media</code> breakpoints just as narrowing the viewport does.</p>

<p>A tabbed interface needs a breakpoint where there is insufficient room to lay out all the tabs horizontally. The quickest way to deal with this is to reconfigure the content into a single column.</p>

<p><img src="https://inclusive-components.design/content/images/2017/10/responsive_small.png" alt="Left: horizontal tabs with the first selected. Right: the tabs in one column, vertically stacked. An arrow indicated the selected tab."></p>

<p>This can no longer be considered a "tabbed interface" visually because the tabs no longer look like <em>tabs</em>. This is not necessarily a problem so long as the selected tab (well, "option") is clearly marked. Non-visually, via screen readers, it presents and behaves the same.</p>

<div role="complementary">  
<h4>Accordions for small viewports?</h4>

<p>Some have made noble attempts to reconfigure tabbed interfaces into accordion interfaces for small viewports. Given that accordions are structured, attributed, and operated completely differently to tabs, I would recommend against this.</p>

<p>Accordions do have the advantage of pairing each heading/button with its content in the source, which is arguably a better browsing experience in a one-column configuration. But the sheer complexity of a responsive tabbed interface/accordion hybrid is just not worth it in performance terms.</p>

<p>Where there are very many tabs or the number of tabs are an unknown quantity, an accordion at <em>all</em> screen widths is a safe bet. Single-column layouts are responsive regardless of content quantity. Easy squeezy.</p>

<img src="https://inclusive-components.design/content/images/2017/10/accordions.png" alt="On the left: The accordion layout has one really long heading label which is not wrapping. On the right: the same accordion narrowed with the long heading label wrapping comfortably.">
</div>

<h2 id="whenpanelsareviews">When panels are views</h2>

<p>You'll recall my note from earlier that making the set of links in site navigation appear like a set of tabs is deceptive: A user should expect the keyboard behaviors of a tabbed interface, as well as focus remaining on a tab in the current page. A link pointing to a different page will load that page and move focus to its document (<code>body</code>) element.</p>

<p>What about the "views" in single-page applications: the different screens found at different routes? Technically, they are closer to the panels of our tab interface than whole web pages. But that's not to say they should be <em>communicated</em> as tab panels, because that's not what a user is likely to expect.</p>

<p>Single-page application views are typically intended to seem like distinct web pages or regions in a web page, so that is the story that should be told. Here are some provisions to make:</p>

<h3 id="uselinks">Use links!</h3>

<p>Make sure the links that allow users to choose between views are indeed links — whether or not those links <code>return false</code> and use JavaScript to switch to the new view. Since these controls will navigate the user (by changing their focus location; see below) the link role is the most appropriate for the behavior. Link elements do not need the <code>link</code> ARIA role attribute; they are communicated as "link" by default.</p>

<p>In <a href="https://heydon.github.io/xiao/#home">Xiao</a>, a progressive enhancement-based router system for single-page applications, standard hash fragments are used to denote views. The links to these fragments will be communicated as <em>"same page links"</em> in most assistive software. By capitalizing on standard browser behavior, the user will be made aware they are being redirected to a new, distinct part of the page/application.</p>

<pre><code>&lt;a href="#some-route"&gt;Some route&lt;/a&gt;  
</code></pre>

<h3 id="managefocus">Manage focus</h3>

<p>Just replacing some content on the page does not automatically move the user to that content or (in the case of blind assistive technology users) alert them to its existence. As covered under <strong>The focus of non-interactive elements</strong> above, you can focus the principle heading of the new route view, or the outer view element. If you are focusing the outer view element, it is recommended it is labeled either directly using <code>aria-label</code> or by the principle heading using <code>aria-labelledby</code>.</p>

<pre><code>&lt;div aria-label="Home" role="region" tabindex="-1"&gt;  
  ...
&lt;/div&gt;  
</code></pre>

<p>When used in conjunction with the <code>region</code> role (as in the above code snippet), when the element is focused the contextual information <em>"Home, region"</em> will be announced in screen readers.</p>

<p>Using Xiao, no region is focused on initial page load. This means focus defaults to the body/document element and the <code>&lt;title&gt;</code> is announced in screen readers (see below).</p>

<h3 id="updatethetitle">Update the <code>&lt;title&gt;</code></h3>

<p>The application name should be appended by the label for the specific view. This conforms to the recommended pattern for static sites where the site name is appended by the page name.</p>

<pre><code>&lt;title&gt;[Application name] | [View name]&lt;/title&gt;  
</code></pre>

<p>You can load a Xiao-routed application at any route by simply including the route's hash fragment in the URL. On the load event, the <code>&lt;title&gt;</code> takes that route's label and screen readers identify the application and the specific route within it.</p>

<h2 id="conclusion">Conclusion</h2>

<p>JavaScript can show and hide or create and destroy content with ease, but these DOM events can have different purposes and meanings depending on the context. In this article, we facilitated the basic show/hide ability of JavaScript to create two quite different interfaces: a tabbed interface and single-page application navigation. </p>

<p>There's really no right or wrong in inclusive design. It's just about trying your hardest to provide a valuable experience to as many people as you can. A large part of this is pairing your presentation and behavior in ways that users — no matter how they are operating or reading your interface — would expect for the task in hand.</p>

<h3 id="checklist">Checklist</h3>

<ul>
<li>Don't provide tabbed interfaces unless they are suited to the use case and are likely to be understood and appreciated by the user. Just because you can doesn't mean you should.</li>
<li>Tables of content and same-page links are a simpler and more robust approach to many of the ostensible use cases for tabbed interfaces.</li>
<li>Make sure interfaces that appear as tabbed interfaces have the semantics and behaviors expected of them.</li>
<li>Single-page applications should not present or behave as tabbed interfaces, despite their shared use of JavaScript to switch between and/or populate content panes.</li>
</ul>]]></content:encoded></item><item><title><![CDATA[A Theme Switcher]]></title><description><![CDATA[<p>My mantra for building web interfaces is, "if it can't be done efficiently, don't do it at all." In fact, I've preached about <a href="https://vimeo.com/190834530">writing less damned code</a> around the UK, Europe, and China. If a feature can only be achieved by taking a significant performance hit, the net effect is</p>]]></description><link>https://inclusive-components.design/a-theme-switcher/</link><guid isPermaLink="false">34ba154f-bba8-4a56-be54-8bccb8b05ada</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Fri, 08 Sep 2017 14:16:33 GMT</pubDate><content:encoded><![CDATA[<p>My mantra for building web interfaces is, "if it can't be done efficiently, don't do it at all." In fact, I've preached about <a href="https://vimeo.com/190834530">writing less damned code</a> around the UK, Europe, and China. If a feature can only be achieved by taking a significant performance hit, the net effect is negative and the feature should be abandoned. That's how critical performance is on the web.</p>

<p>Offering users choices over the display of your interface is friendly, so long as it isn't intrusive. It helps to satisfy the <a href="http://inclusivedesignprinciples.org/#offer-choice">Offer choice</a> inclusive design principle. <em>However</em>, choices such as theme options are nice-to-haves and should only be implemented if it's possible to do so efficiently.</p>

<p>Typically, alternative themes are offered as separate stylesheets that can be switched between using JavaScript. In some cases they represent a performance issue (because an override theme requires loading a lot of additional CSS) and in most cases they represent a maintenance issue (because separate stylesheets have to be kept up to date as the site is further developed).</p>

<p>One of the few types of alternative theme that adds real value to users is a low light intensity "night mode" theme. Not only is it easier on the eyes when reading in the dark, but it also reduces the likelihood of migraine and the irritation of other light sensitivity disorders. As a migraine sufferer, I'm interested!</p>

<p>In this article, I'll be covering how to make an efficient and portable React component that allows users to switch a default light theme into "dark mode" and persist this setting using the <code>localStorage</code> API.</p>

<hr>

<p>Given a light theme (predominantly dark text on light backgrounds) the most efficient course of action is not to provide a completely alternative stylesheet, but to augment the existing styles directly, as tersely as possible. Fortunately, CSS provides the <code>filter</code> property, which allow you to invert colors. Although this property is often associated with image elements, it can be used on any elements, including the root <code>&lt;html&gt;</code> element:</p>

<pre><code>:root {
   filter: invert(100%);
}
</code></pre>

<p>(<strong>Note:</strong> Some browsers support <code>invert()</code> as a shorthand, but not all, so write out <code>100%</code> for better support.)</p>

<p>The only trouble is that <code>filter</code> can only invert <em>stated</em> colors. Therefore, if the element has no background color, the text will invert but the implicit (white) background will remain the same. The result? Light text on a light background.</p>

<p>This is easily fixed by stating a light <code>background-color</code>.</p>

<pre><code>:root {
   background-color: #fefefe;
   filter: invert(100%);
}
</code></pre>

<p>But we may still run into problems with child elements that also have no stated background color. This is where CSS's <code>inherit</code> keyword comes in handy.</p>

<pre><code>:root {
   background-color: #fefefe;
   filter: invert(100%);   
}

* {
   background-color: inherit;
}
</code></pre>

<p>On first impression, this may seems like a lot of power we're wielding, but never fear: the <code>*</code> selector is very low specificity, meaning it only provides a <code>background-color</code> to elements for which one isn't already stated. In practice, <code>#fefefe</code> is just a fallback.</p>

<h2 id="preservingrasterimages">Preserving raster images</h2>

<p>While we are intent on inverting the theme, we're probably not going to want to invert raster images or videos, otherwise the design will become filled with spooky looking negatives. The trick here is to double-invert <code>&lt;img/&gt;</code> tags. The selector I'm using excludes SVG images, because — typically presented as flat color diagrams — they should invert successfully and pleasantly.</p>

<pre><code>:root { 
   background-color: #fefefe;
   filter: invert(100%);
}

* { 
   background-color: inherit;
}

img:not([src*=".svg"]), video {  
   filter: invert(100%);
}
</code></pre>

<p>Clocking in at 153 bytes uncompressed, that's dark theme support pretty much taken care of. If you're not convinced, here's the CSS applied to some popular news sites:</p>

<figure role="group">  
<img src="https://inclusive-components.design/content/images/2017/09/dark_set_1-min.png" alt="The Boston Globe and The Independent, mostly in black with light text">
  <figcaption>The Boston Globe and The Independent</figcaption>
</figure>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/09/dark_set_2-min.png" alt="The New York Times and Private Eye, mostly in black with white text">
  <figcaption>The New York Times and Private Eye</figcaption>
</figure>

<h2 id="thethemeswitchcomponent">The theme switch component</h2>

<p>Since the switch between light (default) and dark (inverted) themes is just an on/off, we can use something simple like the <a href="https://inclusive-components.design/toggle-button/">toggle buttons</a> we explored in an earlier article. However, this time we'll implement the toggle button as part of a <a href="https://react-cn.github.io/react/index.html">React</a> component. There are a few reasons for this:</p>

<ul>
<li>Maximum reusability between the React-based projects many of you are used to working in</li>
<li>Ability to take advantage of React's <code>props</code> and <code>defaultProps</code></li>
<li>Some people think frameworks like React and Angular preclude you from writing accessible HTML somehow, and that falsehood needs to die</li>
</ul>

<p>We're also going to incorporate some progressive enhancement, only showing the component if the browser supports <code>filter: invert(100%)</code>.</p>

<h3 id="settingup">Setting up</h3>

<p>If you don't already have a setup for React development, you can create one easily using <code>create-react-app</code>.</p>

<pre><code>npm i -g create-react-app  
create-react-app theme-switch  
cd theme-switch  
npm start  
</code></pre>

<p>The boilerplate app will now be running at <code>localhost:3000</code>. In the new <code>theme-switch</code> project, our component will be called <strong>ThemeSwitch</strong> and will be included in <code>App.js</code>'s render function as <code>&lt;ThemeSwitch&gt;&lt;/ThemeSwitch&gt;</code>.</p>

<pre><code>class App extends Component {  
  render() {
    return (
      &lt;div className="App"&gt;
        &lt;div className="App-header"&gt;
          &lt;img src={logo} className="App-logo" alt="logo" /&gt;
          &lt;h2&gt;Welcome to React&lt;/h2&gt;
        &lt;/div&gt;
        &lt;p className="App-intro"&gt;
          To get started, edit {gfm-js-extract-pre-1} and save to reload.
        &lt;/p&gt;
        &lt;ThemeSwitch&gt;&lt;/ThemeSwitch&gt;
      &lt;/div&gt;
    );
  }
}
</code></pre>

<p>(<strong>Note:</strong> I'm being lazy and leaving the boilerplate in. To really test the theme switcher, include it alongside a bunch of styled content pulled in from another project. You can include CSS in <code>App.css</code>.)</p>

<p>Don't forget to import the <strong>ThemeSwitch</strong> component at the top of this <code>App.js</code> file:</p>

<pre><code>import ThemeSwitch from './components/ThemeSwitch.js'  
</code></pre>

<h3 id="theskeletoncomponentfile">The skeleton component file</h3>

<p>As implied by the path in that last import line, we'll be working on a file called <code>ThemeSwitch.js</code>, placed in a new "components" folder, so you'll need to create both the folder and the file. The skeleton for <strong>ThemeSwitch</strong> looks like this:</p>

<pre><code>import React, { Component } from 'react';

class ThemeSwitch extends Component {  
  render() {
    // The component's markup, in JSX
  }
}

export default ThemeSwitch;  
</code></pre>

<p>The rendered markup for the switch, imagined in a default/inactive state, would look like this (notes to follow):</p>

<pre><code>&lt;div&gt;  
   &lt;button aria-pressed="false"&gt;
      dark theme:
      &lt;span aria-hidden="true"&gt;off&lt;/span&gt;
   &lt;/button&gt;
   &lt;style media="none"&gt;
      html { filter: invert(100%); background: #fefefe }
      * { background-color: inherit }
      img:not([src*=".svg"]), video { filter: invert(100%) }
   &lt;/style&gt;
&lt;/div&gt;  
</code></pre>

<ul>
<li>Not all toggle buttons are created the same. In this case, we're using <code>aria-pressed</code> to toggle accessible state and an explicit "on"/"off" for sighted users. So that the "on" or "off" part is not read out to contradict the state, it is suppressed from assistive technologies with <code>aria-hidden</code>. Screen reader users will hear "dark theme toggle button, not pressed" or "dark theme toggle button,  pressed" or similar.</li>
<li>The CSS is so terse, we're going to provide it as an embedded stylesheet. This is set to <code>media="none"</code> — or <code>media="screen"</code> when the dark theme is activated</li>
</ul>

<p>This markup will get very messy shortly, as we convert it to JSX.</p>

<h3 id="switchingstate">Switching state</h3>

<p>Our component will be stateful, allowing the user to toggle the dark theme between inactive and active. First we initialize the state on the component's constructor:</p>

<pre><code>constructor(props) {  
   super(props);

   this.state = {
      active: 'false'
   };
}
</code></pre>

<p>To bring things to life, a helper function called <code>isActive()</code> is included, along with a <code>toggle()</code> function that actually toggles the state:</p>

<pre><code>  isActive = () =&gt; this.state.active === true;

  toggle = () =&gt; {
    this.setState({
      active: !this.isActive()
    });
  }
</code></pre>

<p>(<strong>Note:</strong> Arrow functions implicitly return single statements, hence the tersity of the <code>isActive()</code> function.)</p>

<p>In the render function for the component, we can use <code>isActive()</code> to switch the <code>aria-pressed</code> value, the button text, and the value of the stylesheet's <code>media</code> attribute:</p>

<pre><code>return (  
  &lt;div&gt;
    &lt;button aria-pressed={this.isActive()} onClick={this.toggle}&gt;
      dark theme:
      &lt;span aria-hidden="true"&gt;{this.isActive() ? 'on' : 'off'}&lt;/span&gt;
    &lt;/Button&gt;
    &lt;style media={this.isActive() ? 'screen' : 'none'}&gt;
      {this.css}
    &lt;/style&gt;
  &lt;/div&gt;
);
</code></pre>

<figure role="group">  
<img src="https://inclusive-components.design/content/images/2017/09/off_on_themer-1.svg" alt="The two states of the toggle button. When it has aria-pressed false, the text reads dark theme off. When it has aria-pressed true, the text reads dark theme on.">
  <figcaption>Of course, when the dark theme is on,
 the button itself is also inverted.</figcaption>
</figure>

<p>Note the <code>{this.css}</code> part. JSX doesn't support embedding CSS directly, so we have to save it to a variable and enter it here dynamically. In the constructor:</p>

<pre><code>this.css = `  
html { filter: invert(100%); background: #fefefe; }  
* { background-color: inherit }
img:not([src*=".svg"]), video { filter: invert(100%) }`;  
</code></pre>

<h4 id="overcomingbrowserissues">Overcoming browser issues</h4>

<p>Unfortunately, just switching between <code>media="none"</code> and <code>media="screen"</code> does not apply the styles to the page in all browsers. To force a repaint, it turns out we have to rewrite the text content of the <code>&lt;style&gt;</code> tag. The easiest way I found of doing this was to incorporate the <code>trim()</code> method. Curiously, this only seemed to be needed in Chrome.</p>

<pre><code>{this.isActive() ? this.css.trim() : this.css}
</code></pre>

<h3 id="persistingthethemepreference">Persisting the theme preference</h3>

<p>To persist the user's choice of theme, we can use <code>localStorage</code> and React lifecycle methods. First, I'll set an alias for <code>localStorage</code> on the constructor. This suppresses linting errors produced when calling <code>localStorage</code> directly.</p>

<pre><code>this.store = typeof localStorage === 'undefined' ? null : localStorage;  
</code></pre>

<p>Using the <code>componentDidMount</code> method, I can fetch and apply the saved setting after the component mounts to the page. The expression defaults the value to 'false' if the storage item is yet to be created.</p>

<pre><code>componentDidMount() {  
  if (this.store) {
    this.setState({
      active: this.store.getItem('ThemeSwitch') || false
    });
  }
}
</code></pre>

<p>Because state is managed asynchronously in React, it's not reliable to simply save a changed state after it has been augmented. Instead, I need to use the <code>componentDidUpdate</code> method:</p>

<pre><code>componentDidUpdate() {  
  if (this.store) {
    this.store.setItem('ThemeSwitch', this.state.active);
  }
}
</code></pre>

<h3 id="hidingfromunsupportingbrowsers">Hiding from unsupporting browsers</h3>

<p>Some browsers are yet to support <code>filter: invert(100%)</code>. For those browsers, we will hide our theme switch altogether. It's better that it is not available than it is available and doesn't work. With a special <code>invertSupported</code> function, we can query support to set a <code>supported</code> state. </p>

<p>If you've ever used <a href="https://modernizr.com/">Modernizr</a> you might have used a similar CSS property/value test. However, we don't want to use Modernizr because we don't want our component to rely on any dependencies unless completely necessary.</p>

<pre><code>invertSupported (property, value) {  
  var prop = property + ':',
      el = document.createElement('test'),
      mStyle = el.style;
  el.style.cssText = prop + value;
  return mStyle[property];
}

componentDidMount() {  
  if (this.store) {
    this.setState({
      supported: this.invertSupported('filter', 'invert(100%)'),
      active: this.store.getItem('ThemeSwitch') || false
    });
  }
}
</code></pre>

<p>This can be used in our JSX to hide the component interface using the <code>hidden</code> property where support returns false:</p>

<pre><code>&lt;div hidden={!this.state.supported}&gt;  
  &lt;!-- component contents here --&gt;
&lt;/div&gt;  
</code></pre>

<p>In modern browsers, the <code>hidden</code> property will hide the component from assistive technologies and make it unfocusable by keyboard. To make sure older browsers have the same behavior, include the following in your stylesheet:</p>

<pre><code>[hidden] {
  display: none;
}
</code></pre>

<p>Alternatively, you can refuse to render the component contents to the page at all, by returning <code>null</code>.</p>

<pre><code>render() {  
  if (!this.supported) {
    return null;
  }

  return (
    &lt;div&gt;
      &lt;button aria-pressed={this.state.active} onClick={this.toggle}&gt;
        inverted theme: &lt;span aria-hidden="true"&gt;{this.state.active ? 'on' : 'off'}&lt;/span&gt;
      &lt;/button&gt;
      &lt;style media={this.state.active ? 'screen' : 'none'}&gt;
        {this.state.active ? this.css.trim() : this.css}
      &lt;/style&gt;
    &lt;/div&gt;
  );
}
</code></pre>

<div role="complementary">  
  <h4>Windows High Contrast Mode</h4>
  <p>Windows users are offered a number of high contrast themes at the operating system level — some light-on-dark like our inverted theme. In addition to supplying our theme switcher feature, it's important to make sure WHCM is supported as well as possible. Here are some tips:</p>
  <ul>
    <li>Do not use background images as content. Not only will this invert the images in our inverted dark theme, but they'll be eliminated entirely in most Windows high contrast themes. Provide salient, non-decorative images in <code>&lt;img/></code> tags with descriptive <code>alt</code> text values</li>
    <li>For inline SVG icons, use the <code>currentColor</code> value for fill and stroke.
 This way, the icon color will change along with the surrounding text color when the high contrast theme is activated.</li>
    <li>If you need to detect WHCM to make special amendments, you can use the following media query:</li>
  </ul>
  

<pre><code>@media (-ms-high-contrast: active) { 
  /* WHCM-specific code here */
}</code></pre>
</div>

<h3 id="thespanstyletexttransformnonepreserverastersspanprop">The <span style="text-transform: none"><code>preserveRasters</code></span> prop</h3>

<p>Props (component properties) are the standard way to make components configurable. A configurable component can be used in a greater variety of situations and projects and is therefore more inclusive.</p>

<p>In our case, why don't we make it so that the implementor has a choice over whether raster images are indeed preserved, or if they're inverted with everything else. I'll create a <code>preserveRasters</code> prop that takes "true" or "false" values. Here's how it looks on our component:</p>

<pre><code>&lt;ThemeSwitch preserveRasters={false} /&gt;  
</code></pre>

<p>I can query this prop in the formulation of the CSS string, and only re-invert images if its value is "true":</p>

<pre><code>this.css = `  
  html { filter: invert(100%); background: #fefefe; }
  * { background-color: inherit }
  ${this.props.preserveRasters === 'true' ? `img:not([src*=".svg"]), video { filter: invert(100%) }` : ``}`;
</code></pre>

<p>(<strong>Note:</strong> It's quite possible, though slightly ugly, to use ternaries during string interpolation in this way.)</p>

<h4 id="thedefaultvalue">The default value</h4>

<p>To make the component more robust and offer the implementor the option of omitting the prop attribute, we can also supply a <code>defaultProp</code>. The following can be supplied after the component class definition:</p>

<pre><code>ThemeSwitch.defaultProps = { preserveRasters: true }  
</code></pre>

<h3 id="installingthecomponent">Installing the component</h3>

<p>A version of <a href="https://github.com/Heydon/react-theme-switch">this component</a> is available on NPM:</p>

<pre><code>npm i --save react-theme-switch  
</code></pre>

<p>In addition, a plain JavaScript version, based on a checkbox element, is available to play with in the following <a href="https://codepen.io/heydon/pen/Vzyrre">codePen</a>:</p>

<iframe height="265" scrolling="no" title="Theme color inverter with filter" src="//codepen.io/heydon/embed/Vzyrre/?height=265&theme-id=0&default-tab=html,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/Vzyrre/">Theme color inverter with filter</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h3 id="placement">Placement</h3>

<p>The only thing left to do is decide where you're going to put the component in the document. As a rule of thumb, utilities like theme options should be found in a landmark region — just not the <code>&lt;main&gt;</code> region, because the screen reader user expects this content to change between pages. The <code>&lt;header&gt;</code> (<code>role="banner"</code>) or <code>&lt;footer&gt;</code> (<code>role="contentinfo"</code>) are both acceptable. </p>

<p>The switch should appear in the same place on all pages so that, once the user has located it once, they can easily find it again. Take note of the <a href="http://inclusivedesignprinciples.org/#be-consistent">Be consistent</a> inclusive design principle, which applies here.</p>

<h2 id="checklist">Checklist</h2>

<ul>
<li>Only implement nice-to-have features if the performance hit is minimal and the resulting interface does not increase significantly in complexity</li>
<li>Only provide interfaces for supported features. Use feature detection.</li>
<li>Use semantic HTML in your React components — they'll still work!</li>
<li>Use props to make your components more configurable and reusable</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Tooltips & Toggletips]]></title><description><![CDATA[<p>Tooltips — affectionately misnomered as "tootlips" by my friend <a href="https://twitter.com/stevefaulkner">Steve</a> — are a precariously longstanding interface pattern. Literally "tips for tools", they are little bubbles of information that clarify the purpose of otherwise ambiguous controls/tools. A common example is a control that is only represented by a cryptic icon, the meaning</p>]]></description><link>https://inclusive-components.design/tooltips-toggletips/</link><guid isPermaLink="false">0e710b11-c978-4750-812a-058a65b88c66</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Tue, 25 Jul 2017 16:18:21 GMT</pubDate><content:encoded><![CDATA[<p>Tooltips — affectionately misnomered as "tootlips" by my friend <a href="https://twitter.com/stevefaulkner">Steve</a> — are a precariously longstanding interface pattern. Literally "tips for tools", they are little bubbles of information that clarify the purpose of otherwise ambiguous controls/tools. A common example is a control that is only represented by a cryptic icon, the meaning of which the user has yet to learn.</p>

<p>When and how these bubbles transpire is apparently up for debate, since I've encountered many a tooltip and they all seem to behave slightly differently. I've come to the conclusion that these numerous implementations fall into two distinct groups: true tooltips, and a pattern I'm hesitantly calling the "toggletip", coined by the aforementioned Steve in some <a href="https://www.paciellogroup.com/blog/2016/01/simple-standalone-toggletip-widget-pattern/">research and experimentation</a> he did not long ago.</p>

<p>Inclusive design is often about providing the user with the right tool for the job, and the right kind of tooltip to go with that tool. In this article, I'll be looking at situations which might call for a tooltip or else a toggletip, and formulating inclusive implementations for each.</p>

<hr>

<h2 id="thetitleattribute">The <code>title</code> attribute</h2>

<p>We can't talk about tooltips without bringing up the <code>title</code> attribute: the HTML standard for providing contextual information bubbles. The Paciello Group blog pulls no punches in describing the <code>title</code> attribute's contribution to web interfaces:</p>

<blockquote>
  <p>"If you want to hide content from mobile and tablet users as well as assistive tech users and keyboard only users, use the <code>title</code> attribute." — <a href="https://www.paciellogroup.com/blog/2013/01/using-the-html-title-attribute-updated/">The Paciello Group blog</a></p>
</blockquote>

<p>That's <em>pretty bad</em> in terms of inclusion. In fact, the only place I can think of where the <code>title</code> attribute works reliably in screen reader software is on form elements like <code>&lt;input&gt;</code>s. Even then, touch and keyboard users won't get to see the <code>title</code> message appear. In short: just provide a clearly worded, permanently visible label.</p>

<p><img src="https://inclusive-components.design/content/images/2017/07/tooltips_inputs-2.svg" alt="An input with a big, clear, permanent label is marked good. An input with a tiny title revealed on hover is not."></p>

<p>I'm a big supporter of using standard HTML elements and attributes wherever they're available. It's the most efficient and performant way to build usable web interfaces. But, despite being a specification mainstay, the <code>title</code> attribute really isn't fit for purpose. </p>

<p>Then again, we've yet to define that purpose. What <em>should</em> tooltips be used for? And even if we can design them to be usable by the many, do we need them at all?</p>

<h2 id="acasefortooltips">A case for tooltips</h2>

<p>As we already established, tooltips are for clarification; they are for providing <em>missing</em> information. But why should that information be missing in the first place? As I wrote in <a href="https://shop.smashingmagazine.com/products/inclusive-design-patterns">Inclusive Design Patterns</a>, icons can accelerate the understanding of an interface, and help to internationalize it. But icons provided in isolation are always in danger of completely confounding a user — because they don't <em>spell anything out</em>. To users who don't recognize or can't decipher the icon, information is missing.</p>

<p>Most of the time, you should simply be providing text alongside icons. Like the perma-visible field labels I just mentioned, textual labels are the most straightforward way of labeling things and they're automatically screen reader accessible if provided as real text (not images of text).</p>

<p>The usual excuse for <em>not</em> providing textual labels is,  "there's no space". And there likely isn't, if you set out not to include textual labels in the first place. If you treat them as important from the beginning, you will find a way.</p>

<figure role="group">  
<img src="https://inclusive-components.design/content/images/2017/07/text_layouts-1.svg" alt="Left example has four labels next to one another on the same line, meaning the text has to be small. Right example puts them 2 by 2, leaving more space for bigger text.">
<figcaption>There's always room for text if you make it, but some configurations leave more space for text than others.</figcaption>  
</figure>

<p>Tooltips are a last resort, where space really is at a premium — perhaps due to the sheer number of controls, like in the toolbar for a WYSIWYG editor. So, how would we go about designing them to be as inclusive as possible?</p>

<h2 id="inclusivetooltips">Inclusive tooltips</h2>

<p>The first thing to get right is making the text in the tooltip accessible to assistive technologies. There are a couple of different methods for associating the tooltip to the focused control, and we choose between them based on the specific role of that tooltip: Is the tooltip there to provide a primary label or an auxiliary clarification?</p>

<p>A notifications control with a tooltip reading "Notifications" treats the tooltip as a primary label. Alternatively, a tooltip that reads "View notifications and manage settings" is supplementary.</p>

<p><img src="https://inclusive-components.design/content/images/2017/07/primary_or_auxiliary.svg" alt="The left example says notifications and has the caption primary label. The right example has the longer " view="" notifications="" and="" manage="" settings"="" text="" is="" captioned="" auxiliary="" description."=""></p>

<h3 id="tooltipasprimarylabel">Tooltip as primary label</h3>

<p>To associate one element with another as its primary label, you can use <code>aria-labelledby</code>. The relationship is forged by the <code>aria-labelledby</code> and <code>id</code> attributes sharing the same value.</p>

<pre><code>&lt;button class="notifications" aria-labelledby="notifications-label"&gt;  
  &lt;svg&gt;&lt;use xlink:href="#notifications-icon"&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;/button&gt;  
&lt;div role="tooltip" id="notifications-label"&gt;Notifications&lt;/div&gt;  
</code></pre>

<ul>
<li>Note the use of the <code>tooltip</code> role. In practical terms, all this role offers is an assurance that <code>aria-describedby</code> works reliably where supported. As Léonie Watson writes, <a href="https://www.paciellogroup.com/blog/2017/07/short-note-on-aria-label-aria-labelledby-and-aria-describedby/">ARIA labels and descriptions sometimes don't work with all elements</a> unless you incorporate an appropriate role. In this case, the most important role is the implicit button role of the subject <code>&lt;button&gt;</code> element, but <code>role="tooltip"</code> may extend support for this labeling method in some software.</li>
<li>Whatever text content is in the linked SVG, it won't be read out. The <code>aria-labelledby</code> association <em>supersedes</em> the text content of the button as the label.</li>
</ul>

<p>To a screen reader — and its user — the above is now functionally similar to using a simple text label, like this: </p>

<pre><code>&lt;button class="notifications"&gt;Notifications&lt;/button&gt;  
</code></pre>

<p>The tooltip text is available on focus, just as it would be on hover for sighted users. In fact, if all text appeared only on hover, a sighted mouse user's experience of an interface would be somewhat analogous to that of a blind screen reader user.</p>

<div role="complementary">  
<h4>Redundant tooltips</h4>  
<p>All the time as an interface design consultant, I see people providing <code>title</code> attributes to links with identical text nodes.</p>  


<pre><code>&lt;a href="/some/path" title="Heydon's special page">Heydon's special page&lt;/a>
</code></pre>
<p>Since the text node is already perfectly visible, this is completely redundant. It doesn't even add anything for screen readers except — in some cases — repetition.</p>  
</div>

<h4 id="includingnotificationcount">Including notification count</h4>

<p>What if the notifications button showed a count of unread notifications, as these things often do (I'm thinking, of course, of Twitter)? </p>

<p><img src="https://inclusive-components.design/content/images/2017/07/notification_count-1.svg" alt=""></p>

<p>Fortunately, <code>aria-labelledby</code> can accept multiple, space separated <code>id</code>s.</p>

<pre><code>&lt;button class="notifications" aria-labelledby="notifications-count notifications-label"&gt;  
  &lt;svg&gt;&lt;use xlink:href="#notifications-icon"&gt;&lt;/use&gt;&lt;/svg&gt;
  &lt;span id="notifications-count"&gt;3&lt;/span&gt;
&lt;/button&gt;  
&lt;div role="tooltip" id="notifications-label"&gt;Notifications&lt;/div&gt;  
</code></pre>

<p>Despite the <code>#notifications-count</code> element appearing inside the <code>&lt;button&gt;</code>, it does not form the label by itself: It forms the first part of the label as the first <code>id</code> listed in the <code>aria-labelledby</code> value. It is placed where it is so that the designer can take advantage of relative and absolute positioning to arrange the element visually.</p>

<p>To screen reader users, the label is now "3 notifications". This succinctly acts as both a current count of notifications and a reminder that this is the notifications control.</p>

<h3 id="tooltipasauxiliarydescription">Tooltip as auxiliary description</h3>

<p>Now let's try setting up the tooltip as a supplementary description, which is the archetypal form. Like <code>&lt;input&gt;</code> placeholders, tooltips should be for added information and clarification. </p>

<p>Some interactive elements may have accessible descriptions, but all interactive elements need accessible labels. If we're using <code>aria-describedby</code> to connect the tooltip text, we'll need another method for providing the "Notifications" label. Instead of <code>aria-labelledby</code> we can add a visually hidden span to the button's text node, alongside the existing "3" counter.</p>

<pre><code>&lt;button class="notifications" aria-describedby="notifications-count notifications-label"&gt;  
  &lt;svg&gt;&lt;use xlink:href="#notifications-icon"&gt;&lt;/use&gt;&lt;/svg&gt;
  &lt;span id="notifications-count"&gt;3&lt;/span&gt; 
  &lt;span class="visually-hidden"&gt;Notifications&lt;/span&gt;
&lt;/button&gt;  
&lt;div role="tooltip" id="notifications-label"&gt;View and manage notifications settings&lt;/div&gt;  
</code></pre>

<p>The <code>visually-hidden</code> class corresponds to some special CSS we've discussed before on Inclusive Components. It hides the <code>&lt;span&gt;</code> visually without stopping it from being read out in screen readers.</p>

<pre><code>.visually-hidden {
  clip-path: inset(100%);
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
</code></pre>

<p>The prescribed behavior of <code>aria-describedby</code> is to be announced as the last piece of information for the control, after the label and role. In this case: <em>"Notifications button&hellip; View and manage notifications settings"</em> (most screen readers will leave a pause before the description).</p>

<h3 id="interaction">Interaction</h3>

<p>To improve upon the notoriously awful <code>title</code> attribute, our custom tooltips should appear on focus as well as hover. By supplying the tooltip in an element adjacent to the button, we can do this with just CSS:</p>

<pre><code>[role="tooltip"] {
  display: none;
}

button:hover + [role="tooltip"],  
button:focus + [role="tooltip"] {  
  display: block;
}
</code></pre>

<p>However, we may need to wrap the button and tooltip in a container element for positioning purposes:</p>

<pre><code>.button-and-tooltip {
  position: relative;
}

[role="tooltip"] {
  position: absolute;
  /* left/top/right/bottom values as required */
}
</code></pre>

<h2 id="touchinteraction">Touch interaction</h2>

<p>So far this simply doesn't work so well for touch screen users because the focus and active states happen simultaneously. In practice, this means you'll see the tooltip, but only as the button is being pressed.</p>

<p>How <em>much</em> of a problem this is depends on the nature of the app to which the control belongs. How bad is it if the user presses the control without really knowing what it does the first time? How easily can they recover?</p>

<p>There are other things you could try, of course. One might be to suppress the button's action on the first press so it <em>just</em> shows the tooltip that time around. You could take this "tutorial mode" idea further still and show the tooltips as inline text for newcomers, but streamline the interface to just show icons for established users. By then, they should have learned what the icons represent.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/07/new_established.svg" alt="Left example for a new user has icons with text labels. Right example for an established user has just icons">
  <figcaption>In either case, the landing screen for each of the options should have a clear (<code>&lt;h1></code>) heading with the same wording as the labels. Then at least the user knows where the icon took them upon arrival.</figcaption>
</figure>

<p>This would be to do away with tooltips altogether, which is probably for the best anyway. However, the tooltip's sister component — the toggletip — can work for mouse, keyboard <em>and</em> touch users.</p>

<h2 id="inclusivetoggletips">Inclusive toggletips</h2>

<p>Toogletips are like tooltips in the sense that they can provide supplementary or clarifying information. However, they differ by making the control itself supplementary: toggletips exist to reveal information balloons, and serve no other purpose. </p>

<p>Often they take the form of little "i" icons:</p>

<p><img src="https://inclusive-components.design/content/images/2017/07/i-1.svg" alt="A round " i"="" icon="" disclosing="" a="" message="" that="" describes="" what="" notifications="" are."=""></p>

<p>To work by touch just as well as by mouse or keyboard, toggletips are revealed by click rather than by hover and focus. Crucially, this means the <code>aria-describedby</code> association is no longer appropriate. Why? Because a screen reader user would have access to the information before pressing the button, so pressing it would appear not to do anything. Technically, they have <em>access</em> to the information, making the control "accessible" — but the control simply wouldn't make sense. In other words, it's a user experience issue more than a strict accessibility one, but it's important.</p>

<h3 id="toggletipswithliveregions">Toggletips with live regions</h3>

<p>The trick is to make screen readers announce the information after the click event. This is a perfect use case for a <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">live region</a>. We can supply an empty live region, and populate it with the toggletip "bubble" when it is invoked. This will both make the bubble appear visually and cause the live region to announce the tooltip's information.</p>

<p>To follow is the markup with the live region unpopulated. Note the <code>.tooltip-container</code> element, which is provided to help positioning. This element would have <code>position: relative</code>, allowing for absolutely positioning the generated <code>.toggletip-bubble</code> element nearby.</p>

<pre><code>&lt;span class="tooltip-container"&gt;  
  &lt;button type="button" aria-label="more info" data-toggletip-content="This clarifies whatever needs clarifying"&gt;i&lt;/button&gt;
  &lt;span role="status"&gt;&lt;/span&gt;
&lt;/span&gt;  
</code></pre>

<p>Note the <code>type="button"</code> attribution which is to stop some browsers mistaking the button as a submit button when placed inside forms. Here is the markup with the live region populated (after the toggletip button is clicked):</p>

<pre><code>&lt;span class="tooltip-container"&gt;  
  &lt;button type="button" aria-label="more info" data-toggletip-content="This clarifies whatever needs clarifying"&gt;i&lt;/button&gt;
  &lt;span role="status"&gt;
    &lt;span class="toggletip-bubble"&gt;This clarifies whatever needs clarifying&lt;/span&gt;
  &lt;/span&gt;
&lt;/span&gt;  
</code></pre>

<p>The accompanying script and codePen, with notes to follow:</p>

<pre><code>(function() {
  // Get all the toggletip buttons
  var toggletips = document.querySelectorAll('[data-toggletip-content]');

  // Iterate over them
  Array.prototype.forEach.call(toggletips, function (toggletip) {
    // Get the message from the data-content element
    var message = toggletip.getAttribute('data-toggletip-content');

    // Get the live region element
    var liveRegion = toggletip.nextElementSibling;

    // Toggle the message
    toggletip.addEventListener('click', function () {
        liveRegion.innerHTML = '';
        window.setTimeout(function() {
          liveRegion.innerHTML = '&lt;span class="toggletip-bubble"&gt;'+ message +'&lt;/span&gt;';
        }, 100);
    });

    // Close on outside click
    document.addEventListener('click', function (e) {
      if (toggletip !== e.target) {
        liveRegion.innerHTML = '';
      }                        
    });

    // Remove toggletip on ESC
    toggletip.addEventListener('keydown', function(e) {
      if ((e.keyCode || e.which) === 27)
      liveRegion.innerHTML = '';
    });
  });
}());
</code></pre>

<iframe height="265" scrolling="no" title="Toggletip" src="//codepen.io/heydon/embed/zdYdQv/?height=265&theme-id=0&default-tab=js,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/zdYdQv/">Toogletip</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h4 id="notes">Notes</h4>

<ul>
<li>Our button is not a toggle button — at least, not in the usual sense. Instead of clicking the button showing or hiding the bubble, it only shows it. Hiding the bubble is achieved by unfocusing the button, mouse clicking away from the button or pressing escape. </li>
<li>When the button is clicked for a second (or third, fourth etc.) time, the live region is repopulated after a discreet interval, re-announcing the content in screen readers. This is simpler and more intuitive than implementing toggle states (a "message in on" state makes little sense, especially once it has already been read out).</li>
<li>The "discreet interval" (see last item) is implemented using <code>setTimeout</code>. Without it, some setups are not able to register the repopulation of the live region and do not re-announce the contents.</li>
<li>The <code>role="tooltip"</code> attribution is not applicable since we are using <code>role="status"</code> for the live region.</li>
</ul>

<h4 id="progressivelyenhancingtitle">Progressively enhancing <code>title</code></h4>

<p>As discussed, the <code>title</code> attribute is <em>really</em> flaky. But it <em>does</em> at least provide an accessible label to some assistive technologies, available when the button is focused. We could provide the bubble content via <code>title</code> and use this to build the <code>data-toggletip-content</code> attribute on page load. Our script's initial hook now becomes the boolean <code>data-toggletip</code>:</p>

<pre><code>&lt;button data-toggletip aria-label="more info" title="This clarifies whatever needs clarifying"&gt;i&lt;/button&gt;  
</code></pre>

<p>In the script, we need to take the value from <code>title</code> to build <code>data-tooltip-content</code>, then destroy <code>title</code> because we don't need it and it might still appear / get announced if left festering.</p>

<pre><code>var toggletips = document.querySelectorAll('[data-toggletip][title]');

Array.prototype.forEach(toggletips, function (toggletip) {  
  var message = toggletip.getAttribute('title');
  toggletip.setAttribute('data-tooltip-content', message);
  toggletip.removeAttribute('title');
});
</code></pre>

<h4 id="betterprogressiveenhancement">Better progressive enhancement</h4>

<p>A button that doesn't do anything and happens to have a title attribute isn't really a very good baseline. Instead, I would recommend displaying the toggletip's content inline and then enhancing by creating the toggletip button dynamically.</p>

<p>Here's another codePen, which progressively enhances a simple paragraph into a toggletip:</p>

<iframe height="265" scrolling="no" title="Toogletip from paragraph" src="//codepen.io/heydon/embed/Vzwdpy/?height=265&theme-id=0&default-tab=html,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/Vzwdpy/">Toogletip from paragraph</a> by Heydon (<a href="https://codepen.io/heydon">@heydon</a>) on <a href="https://codepen.io">CodePen</a>.  
</iframe>

<h2 id="testsanderrormessages">Tests and error messages</h2>

<p>Something I haven't talked about on Inclusive Components is writing tests, so let's do a little of that here. Don't worry, I don't mean unit tests.</p>

<p>If our toggletip component is to belong to a design system, it may be borrowed and used by lots of different people. By writing tests and including warnings, we can try to ensure it isn't being used improperly.</p>

<p>A toggletip button that isn't a <code>&lt;button&gt;</code> provides a deceptive role to assistive technologies and is not focusable by keyboard (unless it's another, inappropriate focusable element like a hyperlink). In our script, we can detect the element <code>nodeName</code> and return an error message if it is not <code>BUTTON</code>. We use <code>return</code> to stop the remainder of the IIFE (Immediately Invoked Function Expression) from executing.</p>

<pre><code>if (toggletip.nodeName !== 'BUTTON') {  
  console.error('Toggletip buttons need to be &lt;button&gt; elements.')
  return;
}
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/07/error_message.png" alt="The error message screenshot form developer tools"></p>

<h3 id="csstestsanderrormessages">CSS tests and error messages</h3>

<p>In <a href="https://shop.smashingmagazine.com/products/inclusive-design-patterns">Inclusive Design Patterns</a> I write about creating deliberate visual regressions to highlight code errors, and providing error messages in the developer tools CSS inspector.</p>

<p>The error we caught with JavaScript earlier can be caught using the CSS selector <code>[data-tooltip]:not(button)</code>. We can highlight the erroneous element with a red outline, and provide an error message using the made-up <code>ERROR</code> property:</p>

<pre><code>[data-tooltip]:not(button) {
  outline: red solid 0.5em;
  ERROR: Toggletip buttons need to be &lt;button&gt; elements.
}
</code></pre>

<p>Despite being an invalid property, the <code>ERROR</code> will appear in dev tools when the element is inspected.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/07/red_outline.svg" alt="">
  <figcaption>The clear red outline shows there is an error present and guides the developer's DOM inspector cursor.</figcaption>
</figure>

<h2 id="conclusion">Conclusion</h2>

<p>Most of the time, tooltips shouldn't be needed if you provide clear textual labeling and familiar iconography. Most of the time toggletips are a complex way of providing information that could just be part of the document's prose content. But I see each of these components all the time in auditing websites, so I wanted to provide some guidance on how to make the most of them. </p>

<h3 id="checklist">Checklist</h3>

<ul>
<li>If you have space, don't use tooltips or toggletips. Just provide clear labels and sufficient body text.</li>
<li>If it's a tooltip you are looking to use, decide whether the tip's content should be provided as the label or description and choose ARIA properties accordingly.</li>
<li>Don't rely on <code>title</code> attributes. They are not keyboard accessible and are not supported in many screen reader setups.</li>
<li>Don't describe toggletips with <code>aria-describedby</code>. It makes the subject button non-functional to screen reader users.</li>
<li>Don't put interactive content such as close and confirm buttons or links in tooltips or toggletips. This is the job of more complex menu and dialog components.</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Menus & Menu Buttons]]></title><description><![CDATA[<p>Classification is hard. Take crabs, for example. Hermit crabs, porcelain crabs, and horseshoe crabs are not — taxonomically speaking — <em>true</em> crabs. But that doesn&#8217;t stop us using the &#8220;crab&#8221; suffix. It gets more confusing when, over time and thanks to a process called <em>carcinisation</em>, untrue crabs evolve</p>]]></description><link>https://inclusive-components.design/menus-menu-buttons/</link><guid isPermaLink="false">0fddb12f-e324-4fdc-be88-7788b73ebdd5</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Wed, 10 May 2017 09:18:58 GMT</pubDate><content:encoded><![CDATA[<p>Classification is hard. Take crabs, for example. Hermit crabs, porcelain crabs, and horseshoe crabs are not — taxonomically speaking — <em>true</em> crabs. But that doesn&#8217;t stop us using the &#8220;crab&#8221; suffix. It gets more confusing when, over time and thanks to a process called <em>carcinisation</em>, untrue crabs evolve to resemble true crabs more closely. This is the case with king crabs, which are believed to have been hermit crabs in the past. Imagine the size of their shells!</p>

<p>In design, we often make the same mistake of giving different things the same name. They <em>appear</em> similar, but appearances can be deceptive. This can have an unfortunate effect on the clarity of your component library. In terms of inclusion, it may also lead you to repurpose a semantically and behaviorally inappropriate component. Users will expect one thing and get another.</p>

<p>The term &#8220;dropdown&#8221; names a classic example. Lots of things &#8220;drop down&#8221; in interfaces, including the set of <code>&lt;option&gt;</code>s from a <code>&lt;select&gt;</code> element, and the JavaScript-revealed list of links that constitute a navigation submenu. Same name; quite different things. (Some people call these &#8220;pulldowns&#8221;, of course, but let&#8217;s not get into that.)</p>

<p>Dropdowns which constitute a set of options are often called &#8220;menus&#8221;, and I want to talk about these here. We shall be devising a <em>true</em> menu, but there&#8217;s plenty to be said about not-really-true menus along the way.</p>

<hr>

<p>Let&#8217;s start with a quiz. Is the box of links hanging down from the navigation bar in the illustration a menu?</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/dropdown.svg" alt="A navigation bar with includes a shop link, underneath which hangs a set of three further links to dog costumes, waffle irons, and magical orbs respectively."></p>

<p>The answer is no, not a true menu. </p>

<p>It&#8217;s a longstanding convention that navigation schemas are composed of lists of links. A convention nearly as longstanding dictates that sub-navigation should be provided as <em>nested</em> lists of links. If I were to remove the CSS for the component illustrated above, I should see something like the following, except colored blue and in Times New Roman.</p>

<ul>  
<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Home</a></li>

<li><a href="https://inclusive-components.design/menus-menu-buttons/#">About</a></li>

<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Shop</a>


<ul>  
<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Dog costumes</a></li>

<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Waffle irons</a></li>

<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Magical orbs</a></li></ul>  
</li>

<li><a href="https://inclusive-components.design/menus-menu-buttons/#">Contact</a></li>  
</ul>

<p>Semantically speaking, nested lists of links are correct in this context. Navigation systems are really <strong>tables of content</strong> and this is how tables of content are structured. The only thing that really makes us think &#8220;menu&#8221; is the styling of the nested lists and the way they are revealed on hover or focus.</p>

<p>That&#8217;s where some go wrong and start adding WAI-ARIA semantics: <code>aria-haspopup="true"</code>, <code>role="menu"</code>, <code>role="menuitem"</code> etc. There is a place for these, as we&#8217;ll cover, but not here. Here are two reasons why:</p>

<ol>  
<li>ARIA menus are not designated for navigation but for  application behavior. Imagine the menu system for a desktop application.</li>

<li>The top-level link should be usable <em>as a link</em>, meaning it does not behave like a menu button.</li>  
</ol>

<p>Regarding (2): When traversing a navigation region with submenus, one would expect each submenu to appear upon hovering or focusing the &#8220;top level&#8221; link (&#8220;Shop&#8221; in the illustration). This both reveals the submenu and places its own links in focus order. With a little help from JavaScript capturing focus and blur events to persist the appearance of the submenus while needed, someone using the keyboard should be able to tab through each link of each tier, in turn.</p>

<p>Menu buttons which take the <code>aria-haspopup="true"</code> property do not behave like this. They are activated on <em>click</em> and have no other purpose than to reveal a secreted menu. </p>

<p><img src="https://inclusive-components.design/content/images/2017/04/menu_states.svg" alt="Left: a menu button labeled 'menu' with a down-pointing arrow icon and the aria-expanded = false state. Right: The same menu button but with the menu open. This button is in the aria-expanded = true state."></p>

<p>As pictured, whether that menu is open or closed should be communicated with <code>aria-expanded</code>. You should only change this state on click, not on focus. Users do not usually expect an explicit change of state on a mere focus event. In our navigation system, state doesn&#8217;t really change; it&#8217;s just a styling trick. Behaviorally, we can <kbd>Tab</kbd> through the navigation as if no such show/hide trickery were occurring.</p>

<h2 id="theproblemwithnavigationsubmenus">The problem with navigation submenus</h2>

<p>Navigation submenus (or &#8220;dropdowns&#8221; to some) work well with a mouse or by keyboard, but they&#8217;re not so hot when it comes to touch. When you press the top-level &#8220;Shop&#8221; link in our example for the first time, you are telling it to both open the submenu and follow the link.</p>

<p>There are two possible resolutions here:</p>

<ol>  
<li>Prevent the default behavior of top-level links (<code>e.preventDefault()</code>) and script in full WAI-ARIA menu semantics and behavior.</li>

<li>Make sure each top-level destination page has a table of contents as an alternative to the submenu.</li>  
</ol>

<p>(1) is unsatisfactory because, as I noted previously, these kinds of semantics and behaviors are not expected in this context, where links are the subject controls. Plus users could no longer navigate to a top-level page, if it exists.</p>

<div role="complementary">  
<h3>Which devices are touch devices?</h3>  
<p>It&#8217;s tempting to think, &#8220;this isn&#8217;t a great solution, but I&#8217;ll only add it for touch interfaces&#8221;. The problem is: how does one detect if a device has a touch screen?</p> 

<p>You certainly shouldn&#8217;t equate &#8220;small screen&#8221; with &#8220;touch activated&#8221;. Having worked in the same office as folks making touch displays for museums, I can assure you that some of the largest screens around are touch screens. Dual keyboard and touch input laptops are becoming increasingly prolific too.</p>

<p>By the same token, many but not all smaller devices are touch devices. In inclusive design, you cannot afford to make assumptions.</p>  
</div>

<p>Resolution (2) is more inclusive and robust in that it provides a &#8220;fallback&#8221; for users of all inputs. But the scare quotes around the fallback term here are quite deliberate because I actually think in-page tables of content are a <em>superior</em> way of providing navigation.</p>

<p>The award winning <a href="https://www.gov.uk/guidance/content-design/organising-and-grouping-content-on-gov-uk">Government Digital Services team</a> would appear to agree. You may also have seen them on Wikipedia.</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/gds_wikipedia.png" alt="Gov.uk tables of content are minimal with hyphens as list styles. Wikipedia provides a bordered grey box with numbered items. Both are labeled contents"></p>

<h2 id="tablesofcontent">Tables of content</h2>

<p>Tables of content are navigation for related pages or page sections and should be semantically similar to main site navigation regions, using a <code>&lt;nav&gt;</code> element, a list, and a group labeling mechanism.</p>



<pre><code>&lt;nav aria-labelledby="sections-heading"&gt;
  &lt;h2 id="sections-heading"&gt;Products&lt;/h2&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/products/dog-costumes"&gt;Dog costumes&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/products/waffle-irons"&gt;Waffle irons&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/products/magical-orbs"&gt;Magical orbs&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;!-- each section, in order, here --&gt;
</code></pre>

<h3 id="notes">Notes</h3>

<ul>  
<li>In this example, we&#8217;re imagining that each section is its own page, as it would have been in the dropdown submenu. </li>

<li>It&#8217;s important that each of these &#8220;Shop&#8221; pages has the same structure, with this &#8220;Products&#8221; table of content present in the same place. Consistency supports understanding.</li>

<li>The list groups the items and enumerates them in  assistive technology output, such as a screen reader&#8217;s synthetic voice</li>

<li>The <code>&lt;nav&gt;</code> is recursively labeled by the heading using <code>aria-labelledby</code>. This means &#8220;products navigation&#8221; will be announced in most screen readers upon entering the region by <kbd>Tab</kbd>. It also means that &#8220;products navigation&#8221; will be itemized in screen reader element interfaces, from which users can navigate to regions directly.</li>  
</ul>

<h3 id="allononepage">All on one page</h3>

<p>If you can fit all the sections onto one page without it becoming too long and arduous to scroll, even better. Just link to each section&#8217;s hash identifier. For example, <code>href="#waffle-irons"</code> should point to <code>id="waffle-irons"</code>. </p>



<pre><code>&lt;nav aria-labelledby="sections-heading"&gt;
  &lt;h2 id="sections-heading"&gt;Products&lt;/h2&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="#dog-costumes"&gt;Dog costumes&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#waffle-irons"&gt;Waffle irons&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#magical-orbs"&gt;Magical orbs&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;!-- dog costumes section here --&gt;
&lt;section id="waffle-irons" tabindex="-1"&gt;
  &lt;h2&gt;Waffle Irons&lt;/h2&gt;
&lt;/section&gt;
&lt;!-- magical orbs section here --&gt;
</code></pre>

<p>(<strong>Note:</strong> Some browsers are poor at actually sending focus to linked page fragments. Placing <code>tabindex="-1"</code> on the target fragment fixes this.)</p>

<p>Where a site has a lot of content, a carefully constructed information architecture, expressed through the liberal use of tables of content &#8220;menus&#8221; is infinitely preferable to a precarious and unwieldy dropdown system. Not only is it easier to make responsive, and requires less code to do so, but it makes things clearer: where dropdown systems hide structure away, tables of content lay it bare.</p>

<p>Some sites, including the Government Digital Service&#8217;s <a href="https://www.gov.uk/">gov.uk</a>, include index (or &#8220;topic&#8221;) pages that are <em>just</em> tables of content. It&#8217;s such a powerful concept that the popular static site generator Hugo <a href="https://gohugo.io/templates/list/">generates such pages by default</a>.</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/tree.svg" alt="family tree style diagram with topic landing page at top with two individual page offshoots. Each of the individual page offshoots have multiple page section offshoots"></p>

<p>Information architecture is a big part of inclusion. A badly organized site can be as technically compliant as you like, but will still alienate lots of users — especially those with cognitive impairments or those who are pressed for time. </p>

<h2 id="navigationmenubuttons">Navigation menu buttons</h2>

<p>While we&#8217;re on the subject of faux navigation-related menus, it&#8217;d be remiss of me not to talk about navigation menu buttons. You&#8217;ve almost certainly seen these denoted by a three-line &#8220;hamburger&#8221; or &#8220;navicon&#8221; icon.</p>

<p>Even with a pared down information architecture and only one tier of navigation links, space on small screens is at a premium. Hiding navigation behind a button means there&#8217;s more room for the main content in the viewport.</p>

<p>A navigation button is the closest thing we&#8217;ve studied so far to a <em>true</em> menu button. Since it has the purpose of toggling the availability of a menu on click, it should </p>

<ol>  
<li>Identify itself as a button, not a link;</li>

<li>Identify the expanded or collapsed state of its corresponding menu (which, in strict terms, is just a list of links).</li>  
</ol>

<h3 id="progressiveenhancement">Progressive enhancement</h3>

<p>But let&#8217;s not get ahead of ourselves. We ought to be mindful of progressive enhancement and consider how this would work without JavaScript. </p>

<p>In an unenhanced HTML document there&#8217;s not a lot you can do with buttons (except submit buttons but that&#8217;s not even closely related to what we want to achieve here). Instead, perhaps we should start with just a link which takes us to the navigation?</p>



<pre><code>&lt;a href="#navigation"&gt;navigation&lt;/a&gt;
&lt;!-- some content here perhaps --&gt;
&lt;nav id="navigation"&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/about"&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/shop"&gt;Shop&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/content"&gt;Content&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>

<p>There&#8217;s not a lot of point in having the link unless there&#8217;s a lot of content between the link and the navigation. Since site navigation should almost always appear near the top of the source order, there&#8217;s no need. So, really, a navigation menu in the absence of JavaScript should just be&hellip; some navigation.</p>



<pre><code>&lt;nav id="navigation"&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/about"&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/shop"&gt;Shop&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/content"&gt;Content&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>

<p>You enhance this by adding the button, in its initial state, and hiding the navigation (using the <code>hidden</code> attribute):</p>



<pre><code>&lt;nav id="navigation"&gt;
  &lt;button aria-expanded="false"&gt;Menu&lt;/button&gt;
  &lt;ul hidden&gt;
    &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/about"&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/shop"&gt;Shop&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/contact"&gt;Contact&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>

<p>Some older browsers — you know which ones — don&#8217;t support <code>hidden</code>, so remember to put the following in your CSS. It fixes the problem because <code>display: none</code> has the same affect of hiding the menu from assistive technologies and removing the links from focus order.</p>



<pre><code>[hidden] {
  display: none;
}
</code></pre>

<p>Doing one&#8217;s best to support older software is, of course, an act of inclusive design. Some are unable or unwilling to upgrade.</p>

<h3 id="placement">Placement</h3>

<p>Where a lot of people go wrong is by placing the button <em>outside</em> the region. This would mean screen reader users who move to the <code>&lt;nav&gt;</code> using a shortcut would find it to be empty, which isn&#8217;t very helpful. With the list hidden from screen readers, they&#8217;d just encounter this:</p>



<pre><code>&lt;nav id="navigation"&gt;
&lt;/nav&gt;
</code></pre>

<p>Here&#8217;s how we might toggle state:</p>



<pre><code>var navButton = document.querySelector('nav button');
navButton.addEventListener('click', function() {
  let expanded = this.getAttribute('aria-expanded') === 'true' || false;
  this.setAttribute('aria-expanded', !expanded);
  let menu = this.nextElementSibling;
  menu.hidden = !menu.hidden;
});
</code></pre>

<h3 id="ariacontrols">aria-controls</h3>

<p>As I wrote in <a href="http://www.heydonworks.com/article/aria-controls-is-poop">Aria-controls Is Poop</a>, the <code>aria-controls</code> attribute, intended to help screen reader users navigate from a controlling element to a controlled element, is only supported in the JAWS screen reader. So you simply can&#8217;t rely on it.</p>

<p>Without a good method for directing users between elements, you should instead make sure one of the following is true:</p>

<ol>  
<li>The expanded list&#8217;s first link is next in focus order after the button (as in the previous code example).</li>

<li>The first link is focused programmatically upon revealing the list.</li>  
</ol>

<p>In this case, I would recommend (1). It&#8217;s a lot simpler since you don&#8217;t have to worry about moving focus back to the button and on which event(s) to do so. Also, there&#8217;s currently nothing in place to warn users that their focus will be moved to somewhere different. In the true menus we&#8217;ll be discussing shortly, this is the job of <code>aria-haspopup="true"</code>.</p>

<p>Employing <code>aria-controls</code> doesn&#8217;t really do much harm, except that it makes readout in screen readers more verbose. However, some JAWS users may expect it. Here is how it would be applied, using the list&#8217;s <code>id</code> as the cipher:</p>



<pre><code>&lt;nav id="navigation"&gt;
  &lt;button aria-expanded="false" aria-controls="menu-list"&gt;Menu&lt;/button&gt;
  &lt;ul id="menu-list" hidden&gt;
    &lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/about"&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/shop"&gt;Shop&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/contact"&gt;Contact&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>

<h3 id="themenuandmenuitemroles">The menu and menuitem roles</h3>

<p>A <em>true</em> menu (in the WAI-ARIA sense) should identify itself as such using the <code>menu</code> role (for the container) and, typically, <code>menuitem</code> children (<a href="https://www.w3.org/TR/wai-aria/roles#menu">other child roles may apply</a>). These parent and child roles work together to provide information to assistive technologies. Here&#8217;s how a list might be augmented to have menu semantics:</p>



<pre><code>&lt;ul role="menu"&gt;
  &lt;li role="menuitem"&gt;Item 1&lt;/li&gt;
  &lt;li role="menuitem"&gt;Item 2&lt;/li&gt;
  &lt;li role="menuitem"&gt;Item 3&lt;/li&gt;
&lt;/ul&gt;
</code></pre>

<p>Since our navigation menu is beginning to behave somewhat like a &#8220;true&#8221; menu, should these not be present?</p>

<p>The short answer is: no. The long answer is: no, because our list items contain links and <a href="https://w3c.github.io/html-aria/#index-aria-menuitem"><code>menuitem</code> elements are not intended to have interactive descendants</a>. That is, they <em>are</em> the controls in a menu. </p>

<p>We could, of course, suppress the list semantics of the <code>&lt;li&gt;</code>s using <a href="https://www.w3.org/TR/wai-aria/roles#presentation"><code>role="presentation"</code></a> or <code>role="none"</code> (which are equivalent) and place the <code>menuitem</code> role on each link. However, this would suppress the implicit link role. In other words, the example to follow would be announced as &#8220;Home, menu item&#8221;, <em>not</em> &#8220;Home, link&#8221; or &#8220;Home, menu item, link&#8221;. ARIA roles simply override HTML roles.</p>



<pre><code>&lt;!-- will be read as "Home, menu item" --&gt;
&lt;li role="presentation"&gt;
  &lt;a href="/" role="menuitem"&gt;Home&lt;/a&gt;
&lt;/li&gt;
</code></pre>

<p>We want the user to know that they are using a link and can expect link behavior, so this is no good. Like I said, true menus are for (JavaScript driven) application behavior.</p>

<p>What we&#8217;re left with is a kind of hybrid component, which isn&#8217;t quite a true menu but at least tells users whether the list of links is open, thanks to the <code>aria-expanded</code> state. This is a perfectly satisfactory pattern for navigation menus.</p>

<div role="complementary">  
<h3>The <code>&lt;select></code> element</h3>

<p>If you&#8217;ve been involved in responsive design from the beginning, you may remember a pattern whereby navigation was condensed into a <code>&lt;select></code> element for narrow viewports.</p>

<img src="https://inclusive-components.design/content/images/2017/04/select_phone.svg" alt="handset with select element showing &#8220;home&#8221; selected at top of viewport">

<p>As with the checkbox-based <a href="https://inclusive-components.design/toggle-button/">toggle buttons we discussed</a>, using a native element that behaves somewhat as intended without additional scripting is a good choice for efficiency and — especially on mobile — performance. And <code>&lt;select></code> elements <em>are</em> menus of sorts, with similar semantics to the button-triggered menu we shall soon be constructing.</p>

<p>However, just as with the checkbox toggle button, we&#8217;re using an element associated with entering input, not simply making a choice. This is likely to cause confusion for many users — especially since this pattern uses JavaScript to make the selected <code>&lt;option></code> behave like a link. The unexpected change of context this elicits is considered a failure according to WCAG&#8217;s <a href="https://www.w3.org/TR/WCAG20/#consistent-behavior-unpredictable-change">3.2.2 On Input (Level A)</a> criterion.</p>  
</div>

<h2 id="truemenus">True menus</h2>

<p>Now that we&#8217;ve had the discussion about false menus and quasi-menus, the time has arrived to create a <em>true</em> menu, as opened and closed by a true menu button. From here on in I will refer to the button and menu together as simply a &#8220;menu button&#8221;. </p>

<p>But in what respects will our menu button be true? Well, it&#8217;ll be a menu component intended for choosing options in the subject application, which implements all the expected semantics and corresponding behaviors to be considered conventional for such a tool.</p>

<p>As mentioned already, these conventions come from desktop application design. ARIA attribution and JavaScript governed focus management are needed to imitate them fully. Part of the purpose of ARIA is to help web developers create rich web experiences without breaking with usability conventions forged in the native world.</p>

<p>In this example, we&#8217;ll imagine our application is some sort of game or quiz. Our menu button will let the user choose a difficulty level. With all the semantics in place, the menu looks like this:</p>



<pre><code>&lt;button aria-haspopup="true" aria-expanded="false"&gt;
  Difficulty
  &lt;span aria-hidden="true"&gt;&amp;#x25be;&lt;/span&gt;
&lt;/button&gt;
&lt;div role="menu"&gt;
  &lt;button role="menuitem"&gt;Easy&lt;/button&gt;
  &lt;button role="menuitem"&gt;Medium&lt;/button&gt;
  &lt;button role="menuitem"&gt;Incredibly Hard&lt;/button&gt;
&lt;/div&gt;
</code></pre>

<h3 id="notes-1">Notes</h3>

<ul>  
<li>The <code>aria-haspopup</code> property simply indicates that the button secretes a menu. It acts as warning that, when pressed, the user will be moved to the &#8220;popup&#8221; menu (we&#8217;ll cover focus behavior shortly). Its value does not change —  it remains as <code>true</code> at all times.</li>

<li>The <code>&lt;span&gt;</code> inside the button contains the unicode point for a black down-pointing small triangle. This convention indicates visually what <code>aria-haspopup</code> does non-visually — that pressing the button will reveal something below it. The <code>aria-hidden="true"</code> attribution prevents screen readers from announcing <em>&#8220;down pointing triangle&#8221;</em> or similar. Thanks to <code>aria-haspopup</code>, it&#8217;s not needed in the non-visual context.</li>

<li>The <code>aria-haspopup</code> property is complemented by <code>aria-expanded</code>. This tells the user whether the menu is currently in an open (expanded) or closed (collapsed) state by toggling between <code>true</code> and <code>false</code> values.</li>

<li>The menu itself takes the (aptly named) <code>menu</code> role. It takes descendants with the <code>menuitem</code> role. They do not need to be direct children of the <code>menu</code> element, but they are in this case — for simplicity.</li>  
</ul>

<h2 id="keyboardandfocusbehavior">Keyboard and focus behavior</h2>

<p>When it comes to making interactive controls keyboard accessible, the best thing you can do is use the right elements. Because we&#8217;re using <code>&lt;button&gt;</code> elements here, we can be assured that click events will fire on <kbd>Enter</kbd> and <kbd>Space</kbd> keystrokes, as specified in <a href="https://developer.mozilla.org/en/docs/Web/API/HTMLButtonElement">the HTMLButtonElement interface</a>. It also means that we can disable the menu items using the button-associated <code>disabled</code> property.</p>

<p>There&#8217;s a lot more to menu button keyboard interaction, though. Here&#8217;s a summary of all the focus and keyboard behavior we&#8217;re going to implement, based on <a href="https://www.w3.org/TR/wai-aria-practices-1.1/#menubutton">WAI-ARIA Authoring Practices 1.1</a>:</p>

<table>  
  <tr>
    <th scope="row">
      <kbd>Enter</kbd>, <kbd>Space</kbd> or <kbd>↓</kbd> on the menu button
    </th>
    <td>Opens the menu</td>
  </tr>
  <tr>
    <th scope="row">
      <kbd>↓</kbd> on a menu item
    </th>
    <td>Moves focus to the next menu item, or the first menu item if you&#8217;re on the last one</td>
  </tr>
  <tr>
    <th scope="row">
      <kbd>↑</kbd> on a menu item
    </th>
    <td>Moves focus to the previous menu item, or the last menu item if you&#8217;re on the first one</td>
  </tr>
  <tr>
    <th scope="row">
      <kbd>↑</kbd> on the menu button
    </th>
    <td>Closes the menu if open</td>
  </tr>
  <tr>
    <th scope="row">
      <kbd>Esc</kbd> on a menu item
    </th>
    <td>Closes the menu and focuses the menu button</td>
  </tr>
</table>

<p>The advantage of moving focus between menu items using the arrow keys is that <kbd>Tab</kbd> is preserved for moving out of the menu. In practice, this means users don&#8217;t have to move through every menu item to exit the menu — a huge improvement for usability, especially where there are many menu items.</p>

<p>The application of <code>tabindex="-1"</code> makes the menu items unfocusable by <kbd>Tab</kbd> but preserves the ability to focus the elements programmatically, upon capturing key strokes on the arrow keys.</p>



<pre><code>&lt;button aria-haspopup="true" aria-expanded="false"&gt;
  Difficulty
  &lt;span aria-hidden="true"&gt;&amp;#x25be;&lt;/span&gt;
&lt;/button&gt;
&lt;div role="menu"&gt;
  &lt;button role="menuitem" tabindex="-1"&gt;Easy&lt;/button&gt;
  &lt;button role="menuitem" tabindex="-1"&gt;Medium&lt;/button&gt;
  &lt;button role="menuitem" tabindex="-1"&gt;Incredibly Hard&lt;/button&gt;
&lt;/div&gt;
</code></pre>

<h3 id="theopenmethod">The open method</h3>

<p>As part of a sound API design, we can construct methods for handling the various events.</p>

<p>For example, the <code>open</code> method needs to switch the <code>aria-expanded</code> value to &#8220;true&#8221;, change the menu&#8217;s hidden property to <code>false</code>, and focus the first <code>menuitem</code> in the menu that isn&#8217;t disabled:</p>



<pre><code>MenuButton.prototype.open = function () {
  this.button.setAttribute('aria-expanded', true);
  this.menu.hidden = false;
  this.menu.querySelector(':not([disabled])').focus();

  return this;
}
</code></pre>

<p>We can execute this method where the user presses the down key on a focused menu button instance:</p>



<pre><code>this.button.addEventListener('keydown', function (e) {
  if (e.keyCode === 40) {
    this.open();
  }
}.bind(this));
</code></pre>

<p>In addition, a developer using this script will now be able to open the menu programmatically:</p>



<pre><code>exampleMenuButton = new MenuButton(document.querySelector('[aria-haspopup]'));

exampleMenuButton.open();
</code></pre>

<div role="complementary">  
  <h3>The checkbox hack</h3>
  <p>As much as possible, it&#8217;s better not to use JavaScript unless you need to. Involving a third technology on top of HTML and CSS is necessarily an increase in systemic  complexity and fragility. However, not all components can be satisfactorily built without JavaScript in the mix.
</p>  

<p>In the case of menu buttons, an enthusiasm for making  them &#8220;work without JavaScript&#8221; has led to something called the checkbox hack. This is where the checked (or unchecked)  
 state of a hidden checkbox is used to toggle the visibility of a menu element using CSS.</p>

<pre><code>/* menu closed */
[type="checkbox"] + [role="menu"] {
  display: none;
}

/* menu open */
[type="checkbox"]:checked + [role="menu"] {
  display: block;
}
</code></pre>

<p>To screen reader users, the checkbox role and checked state are nonsensical in this context. This can be partly overcome by adding <code>role="button"</code> to the checkbox.</p>  

<pre><code>&lt;input type="checkbox" role="button" aria-haspopup="true" id="toggle"&gt;
</code></pre>

<p>Unfortunately, this suppresses the implicit checked state communication, depriving us of JavaScript-free state feedback (poor though it would have been as &#8220;checked&#8221; in this context).</p> 

<p>But it <em>is</em> possible to spoof <code>aria-expanded</code>. We just need to supply our label with two spans as below.</p>  

<pre><code>&lt;input type="checkbox" role="button" aria-haspopup="true" id="toggle" class="vh"&gt;
&lt;label for="toggle" data-opens-menu&gt;
  Difficulty
  &lt;span class="vh expanded-text"&gt;expanded&amp;lt;/span&gt;
  &lt;span class="vh collapsed-text"&gt;collapsed&lt;/span&gt;
  &lt;span aria-hidden="true"&gt;&amp;#x25be;&lt;/span&gt;
&lt;/label&gt;
</code></pre>

<p>These are both visually hidden using <a href="http://a11yproject.com/posts/how-to-hide-content/">the <code>visually-hidden</code> class</a>, but — depending on which state we&#8217;re in — only one is hidden to screen readers as well. That is, only one has <code>display: none</code>, and this is determined by the extant (but not communicated) checked state:</p>  

<pre><code>/* class to hide spans visually */
.vh { 
  position: absolute !important;
  clip: rect(1px, 1px, 1px, 1px);
  padding:0 !important;
  border:0 !important;
  height: 1px !important;
  width: 1px !important;
  overflow: hidden;
}

/* reveal the correct state wording 
to screen readers based on state */
[type="checkbox"]:checked + label .expanded-text {
  display: inline;
}

[type="checkbox"]:checked + label .collapsed-text {
  display: none;
}

[type="checkbox"]:not(:checked) + label .expanded-text {
  display: none;
}

[type="checkbox"]:not(:checked) + label .collapsed-text {
  display: inline;
}
</code></pre>

<p>This is clever and all, but our menu button is still incomplete since the expected focus behaviors we&#8217;ve been discussing simply cannot be implemented without JavaScript.</p>

<p>These behaviors are conventional and expected, making the button more usable. However, if you really need to implement a menu button without JavaScript, this is about as close as you can get. Considering the cut-down navigation menu button I covered previously offers menu content that is <em>not</em> JavaScript dependent itself (i.e. links), this approach may be a suitable option.</p>

<p>For fun, <a href="https://codepen.io/heydon/pen/afdeffcc8a349ab8138e32573ec85cd3">here&#8217;s a codePen implementing a JavaScript-free navigation menu button</a>.</p>

<iframe height="265" scrolling="no" title="Menu button example no JS" src="//codepen.io/heydon/embed/afdeffcc8a349ab8138e32573ec85cd3/?height=265&theme-id=0&default-tab=css,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/afdeffcc8a349ab8138e32573ec85cd3/">Menu button example no JS</a> by Heydon (<a href="http://codepen.io/heydon">@heydon</a>) on <a href="http://codepen.io">CodePen</a>.  
</iframe>

<p>(<strong>Note:</strong> Only <kbd>Space</kbd> opens the menu.)</p>

<p></p></div><p></p>

<h3 id="thechooseevent">The &#8220;choose&#8221; event</h3>

<p>Executing some methods should emit events so that we can set up listeners. For example, we can emit a <code>choose</code> event when a user clicks a menu item. We can set this up using <code>CustomEvent</code>, which lets us pass an argument to the event&#8217;s <code>detail</code> property. In this case, the argument (&#8220;choice&#8221;) would be the chosen menu item&#8217;s DOM node.</p>

<pre><code>MenuButton.prototype.choose = function (choice) {
  // Define the 'choose' event 
  var chooseEvent = new CustomEvent('choose', {
    detail: {
      choice: choice
    }
  });
  // Dispatch the event
  this.button.dispatchEvent(chooseEvent);

  return this;
}
</code></pre>

<p>There are all sorts of things we can do with this mechanism. Perhaps we have a live region set up with an <code>id</code> of <code>menuFeedback</code>:</p>

<pre><code>&lt;div role="alert" id="menuFeedback"&gt;&lt;/div&gt;
</code></pre>

<p>Now we can set up a listener and populate the live region with the information secreted inside the event:</p>

<pre><code>exampleMenuButton.addEventListener('choose', function (e) {
  // Get the node's text content (label)
  var choiceLabel = e.details.choice.textContent;

  // Get the live region node
  var liveRegion = document.getElementById('menuFeedback');

  // Populate the live region
  liveRegion.textContent = `Your difficulty level is  ${choiceLabel}`;
}):
</code></pre>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/05/live_region_triggered-1.svg" alt="On the left, the menu is open and the Incredibly Hard difficulty level is focused. On the right, the menu has disappeared and the difficulty menu button is focused. Above it, the live region (prefixed with an information icon) reads your difficulty level is incredibly hard.">
<figcaption>When a user chooses an option, the menu closes and focus is returned to the menu button. It&#8217;s important users are returned to the triggering element after the menu is closed.</figcaption>  
</figure>

<p>When a menu item is selected, the screen reader user will hear, <em>&#8220;You chose [menu item&#8217;s label]&#8221;</em>. A live region (defined here with the <code>role="alert"</code> attribution) announces its content in screen readers whenever that content changes. The live region isn&#8217;t mandatory, but it is an example of what might happen in the interface as a  response to the user making a menu choice.</p>

<h2 id="persistingchoices">Persisting choices</h2>

<p>Not all menu items are for choosing persistent settings. Many just act like standard buttons which make something in the interface happen when pressed. However, in the case of our difficulty menu button, we&#8217;d like to indicate which is the current difficulty setting — the one chosen last.</p>

<p>The <code>aria-checked="true"</code> attribute works for items that, instead of <code>menuitem</code>, take the <code>menuitemradio</code> role. The enhanced markup, with the second item checked (<em>set</em>) looks like this:</p>

<pre><code>&lt;button aria-haspopup="true" aria-expanded="false"&gt;
  Difficulty
  &lt;span aria-hidden="true"&gt;&amp;#x25be;&lt;/span&gt;
&lt;/button&gt;
&lt;div role="menu"&gt;
  &lt;button role="menuitemradio" tabindex="-1"&gt;Easy&lt;/button&gt;
  &lt;button role="menuitemradio" aria-checked="true"  tabindex="-1"&gt;Medium&lt;/button&gt;
  &lt;button role="menuitemradio" tabindex="-1"&gt;Incredibly Hard&lt;/button&gt;
&lt;/div&gt;
</code></pre>

<p>Native menus on many platforms indicate chosen items using check marks. We can do that with no trouble using a little extra CSS:</p>

<pre><code>[role="menuitem"][aria-checked="true"]::before {
  content: '\2713\0020';
}
</code></pre>

<p>While traversing the menu with a screen reader running, focusing this checked item will prompt an announcement like <em>&#8220;check mark, Medium menu item, checked&#8221;</em>.</p>

<p>The behavior on opening a menu with a checked <code>menuitemradio</code> differs slightly. Instead of focusing the first (enabled) item in the menu, the <em>checked</em> item is focused instead.</p>

<p><img src="https://inclusive-components.design/content/images/2017/05/menuitemradio.svg" alt="The menu button starts with the menu unopened. On opening the second (Medium) difficulty setting is focused. It is prefixed with a check mark based on the aria-checked attribute's presence."></p>

<p>What&#8217;s the benefit of this behavior? The user (any user) is reminded of their previously selected option. In menus with numerous incremental options (for example, a set of zoom levels), people operating by keyboard are placed in the optimal position to make their adjustment.</p>

<h2 id="usingthemenubuttonwithascreenreader">Using the menu button with a screen reader</h2>

<p>In this video, I&#8217;ll show you what it&#8217;s like to use the menu button with the Voiceover screen reader and Chrome. The example uses items with <code>menuitemradio</code>, <code>aria-checked</code> and the focus behavior discussed. Similar experiences can be expected across the gamut of popular screen reader software.</p>

<style>.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</style>

<div class="embed-container"><iframe src="https://www.youtube.com/embed/Aw_HMHdId88" frameborder="0" allowfullscreen></iframe></div>

<h2 id="inclusivemenubuttonongithub">Inclusive Menu Button on Github</h2>

<p><a href="https://twitter.com/HugoGiraudel">Hugo Giraudel</a> and I have worked together on creating a menu button component with the API features I have described, and more. You have Hugo to thank for many of these features, since they were based on the work they did on <a href="https://github.com/edenspiekermann/a11y-dialog">a11y-dialog</a> — an accessible modal dialog. It is <a href="https://github.com/Heydon/inclusive-menu-button">available on Github</a> and NPM.</p>

<pre><code>npm i inclusive-menu-button --save
</code></pre>

<p>In addition, Hugo has created a <a href="https://github.com/HugoGiraudel/react-menu-button">React version</a> for your delectation.</p>

<h2 id="checklist">Checklist</h2>

<ul>  
<li>Don&#8217;t use ARIA menu semantics in navigation menu systems.</li>

<li>On content heavy sites, don&#8217;t hide structure away in nested dropdown-powered navigation menus.</li>

<li>Use <code>aria-expanded</code> to indicate the open/closed state of a button-activated navigation menu.</li>

<li>Make sure said navigation menu is next in focus order after the button that opens/closes it.</li>

<li>Never sacrifice usability in the pursuit of JavaScript-free solutions. It&#8217;s vanity.</li>  
</ul>]]></content:encoded></item><item><title><![CDATA[A Todo List]]></title><description><![CDATA[<p>According to tradition, each new javascript framework is put through its paces in the implementation of a simple todo list app: an app for creating and deleting todo list entries. The first Angular.js example I ever read was a todo list. Adding and removing items from todo lists demonstrates</p>]]></description><link>https://inclusive-components.design/a-todo-list/</link><guid isPermaLink="false">ab5969a0-fc8d-4058-8d41-e052e0761c86</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Fri, 07 Apr 2017 13:16:22 GMT</pubDate><content:encoded><![CDATA[<p>According to tradition, each new javascript framework is put through its paces in the implementation of a simple todo list app: an app for creating and deleting todo list entries. The first Angular.js example I ever read was a todo list. Adding and removing items from todo lists demonstrates the immediacy of the single-page application view/model relationship.</p>

<p><a href="http://todomvc.com/">TodoMVC</a> compares and contrasts todo app implementations of popular MV* frameworks including Vue.js, Angular.js, and Ember.js. As a developer researching technology for a new project, it enables you to find the most intuitive and ergonomic choice for your needs.</p>

<p>The inclusive design of a todo list interface is, however, framework agnostic. Your user doesn&#8217;t care if it&#8217;s made with Backbone or React; they just need the end product to be accessible and easy to use. Unfortunately, each of the identical implementations in <a href="http://todomvc.com/">TodoMVC</a> have some shortcomings. Most notably, the delete functionality only appears on hover, making it an entirely inaccessible feature by keyboard.</p>

<p>In this article, I&#8217;ll be building an integrated todo list component from the ground up. But what you learn doesn&#8217;t have to apply <em>just</em> to todo lists — we&#8217;re really exploring how to make the basic creation and deletion of content inclusive.</p>

<hr>

<p>Unlike the simple, single element <a href="https://inclusive-components.club/toggle-button">toggle buttons</a> of the previous article, managed lists have a few moving parts. This is what we&#8217;re going to make:</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/04/todo_list.svg" alt="A bold heading reading &#8220;My Todo List&#8221; introduces three todo list items on separate lines. These each have a check box to their left and a bin icon to their right. Underneath them is a text field with a placeholder of &#8220;E.g. Adopt an owl&#8221; and an Add button. The first todo list item&#8217;s checkbox is checked and its text (pick up kids from school) is crossed out to show that it is done.">
</figure>

<h2 id="theheading">The heading</h2>

<p>A great deal of usability is about labels. The <code>&lt;label&gt;</code> element provides labels to form fields, of course. But simple text nodes provided to buttons and links are also labels: they tell you what those elements do when you press them.</p>

<p>Headings too are labels, giving names to the sections (regions, areas, modules) that make up an interface. Whether you are creating a static document, like a blog post, or an interactive single-page application, each major section in the content of that page should almost certainly be introduced by a heading. Our todo list&#8217;s name, &#8220;My Todo List&#8221; in this case, should be marked up accordingly.</p>

<pre><code>&lt;h1&gt;My Todo List&lt;/h1&gt;
</code></pre>

<p>It&#8217;s a very <em>on the nose</em> way of demarcating an interface, but on the nose is good. We don&#8217;t want our users having to do any detective work to know what it is they&#8217;re dealing with.</p>

<h3 id="headinglevel">Heading level</h3>

<p>Determining the correct level for the heading is often considered a question of importance, but it&#8217;s actually a question of <em>belonging</em>. If our todo list is the sole content within the <code>&lt;main&gt;</code> content of the page, it should be level 1, as in the previous example. There&#8217;s nothing surrounding it, so it&#8217;s at the highest level in terms of depth.</p>

<p>If, instead, the todo list is provided as supplementary content, it should have a level which reflects that. For example, if the page is about planning a holiday, a &#8220;Things to pack&#8221; todo list may be provided as a supplementary tool.</p>

<ul>  
<li>Plan for my trip (<code>&lt;h1&gt;</code>)


<ul>  
<li>Places to get drunk (<code>&lt;h2&gt;</code>)


<ul>  
<li>Bars (<code>&lt;h3&gt;</code>)</li>

<li>Clubs (<code>&lt;h3&gt;</code>) </li></ul>  
</li>

<li>Things to pack (todo list) (<code>&lt;h2&gt;</code>)</li></ul>  
</li>  
</ul>

<p>In the above example, both &#8220;Bars&#8221; and &#8220;Clubs&#8221; belong to &#8220;Places to get drunk&#8221;, which belongs to &#8220;Plan for my trip&#8221;. That&#8217;s three levels of belonging, hence the <code>&lt;h3&gt;</code>s.</p>

<p>Even if you feel that your packing todo list is less important than establishing which bars are good to visit, it&#8217;s still on the same <em>level</em> in terms of belonging, so it must have the same heading level.</p>

<p>As well as establishing a good visual hierarchy, the structure described by logically nested sections gives screen reader users a good feel for the page. Headings are also harnessed as navigational tools by screen readers. For example, in JAWS, the <kbd>2</kbd> key will take you to the next section labeled by an <code>&lt;h2&gt;</code> heading. The generic <kbd>h</kbd> key will take you to the next heading of any level.</p>

<aside>  
  <h3>The <code>&lt;section></code> element</h3>
  <p>With all this talk of sections, surely we should be using <code>&lt;section></code> elements, right? Maybe. Here are a couple of things to consider:</p>
  <ol>
    <li>Heading elements already describe sections. That is, the content that starts with a heading and ends just before a heading of the same level is a <em>de facto</em> section.</li>
    <li>If you do use a <code>&lt;section></code> element, you still need to provide a heading to it, otherwise it is an unlabeled section.</li>
  </ol>
  <p>In practice, the value added by <code>&lt;section></code> elements is limited, but still worth noting:</p>
  <ol>
    <li>Some screen readers will announce the start and end of sections when their users are traversing the page element-to-element.</li>
    <li>Some screen readers provide region navigation. For example, in JAWS, <code>&lt;section></code>s count as &#8220;regions&#8221; and can be moved between using <kbd>r</kbd> and <kbd>Shift</kbd> + <kbd>r</kbd>.</li>
    <li>They can make code organization clearer by providing container elements for sections of the page.</li>
  </ol>

  <p>To really make the most of <code>&lt;section></code>s you should label them recursively. That is, by connecting their headings to the <code>&lt;section></code> elements themselves using <code>aria-labelledby</code>:</p>


<pre><code>&lt;section aria-labelledby="todos-label"&gt;
  &lt;h1 id="todos-label"&gt;My Todo List&lt;/h1&gt;
  &lt;!-- content --&gt;
&lt;/section&gt;
</code></pre>

<p>(Note that the <code>aria-labelledby</code> value must match the heading&#8217;s <code>id</code> value.)</p>

<p>This effectively provides a group label to the section, meaning the label will be announced in some screen reader software upon entering the section by focus. Running the NVDA screen reader, when I enter the section and focus the first checkbox, I hear <em>&#8220;My Todo List region, list with three items, pick up kids from school checkbox,  checked.&#8221;</em> It&#8217;s helpful to provide this contextual information to users navigating by focus rather than by region or heading.</p>  
</aside>

<h2 id="thelist">The list</h2>

<p>I talk about the virtues of lists in <em><a href="https://shop.smashingmagazine.com/products/inclusive-design-patterns">Inclusive Design Patterns</a></em>. Alongside headings, lists help to give pages structure. Without headings or lists, pages are featureless and monotonous, making them very difficult to unpick both visually and non-visually.</p>

<p>Not all lists need to be bullet lists, showing a <code>list-style</code>, but there should be some visual indication that the items within the list are similar or equivalent; that they belong together. Non-visually, using the <code>&lt;ul&gt;</code> or <code>&lt;ol&gt;</code> container means the list is identified when encountered and its items are enumerated. For our three-item todo list, screen readers should announce something like, <em>&#8220;list of three items&#8221;</em>.</p>

<p>A todo list is, as the name suggests, a list. Since our particular todo list component makes no assertions about priority, an unordered list is fine. Here&#8217;s the structure for a static version of our todo list (the adding, deleting, and checking functionality has not yet been added):</p>

<pre><code>&lt;section aria-labelledby="todos-label"&gt;
  &lt;h1 id="todos-label"&gt;My Todo List&lt;/h1&gt;
  &lt;ul&gt;
    &lt;li&gt;
      Pick up kids from school
    &lt;/li&gt;
    &lt;li&gt;
      Learn Haskell
    &lt;/li&gt;
    &lt;li&gt;
      Sleep
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/section&gt;
</code></pre>

<h3 id="emptystate">Empty state</h3>

<p>Empty states are an aspect of UI design which you <a href="https://techcrunch.com/2015/11/22/the-most-overlooked-aspect-of-ux-design-could-be-the-most-important/">neglect at your peril</a>. Inclusive design has to take user lifecycles into consideration, and some of your most vulnerable users are new ones. To them your interface is unfamiliar and, without carefully leading them by the hand, that unfamiliarity can be off-putting.</p>

<p>With our heading and &#8220;add&#8221; input present it may be obvious to some how to proceed, even without example todo items or instructions present. But your interface may be less familiar and more complex than this simple todo list, so let&#8217;s add an empty state anyway — for practice.</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/todo_list_empty-2.svg" alt=""></p>

<h4 id="revealingtheemptystate">Revealing the empty state</h4>

<p>It&#8217;s quite possible, of course, to use our data to determine whether the empty state should be present. In Vue.js, we might use a <code>v-if</code> block:</p>

<pre><code>&lt;div class="empty-state" v-if="!todos.length"&gt;
  &lt;p&gt;Either you've done everything already or there are still things to add to your list. Add your first todo &amp;#x2193;&lt;/p&gt;
&lt;/div&gt;
</code></pre>

<p>But all the state information we need is actually already in the DOM, meaning all we need in order to switch between showing the list and showing the empty-state is CSS.</p>

<pre><code>.empty-state, ul:empty {
  display: none;
}

ul:empty + .empty-state {
  display: block;
}
</code></pre>

<p>This is more efficient because we don&#8217;t have to query the data or change the markup. It&#8217;s also screen reader accessible: <code>display: none</code> makes sure the element in question is hidden both visually and from screen reader software.</p>

<p>All pseudo-classes pertain to implicit states. The <code>:empty</code> pseudo-class means the element is in an empty state; <code>:checked</code> means it&#8217;s in a checked state; <code>:first-child</code> means it&#8217;s positioned at the start of a set. The more you leverage these, the less DOM manipulation is required to add and change state with JavaScript.</p>

<h2 id="addingatodoitem">Adding a todo item</h2>

<p>We&#8217;ve come this far without discussing the adding of todos. Let&#8217;s do that now. Beneath the list (or empty state if the list is empty) is a text input and &#8220;add&#8221; button:</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/add_todo.svg" alt="A text input with 'e g adopt an owl' placeholder with an 'add' button to its right"></p>

<h3 id="formornoform">Form or no form?</h3>

<p>It&#8217;s quite valid in HTML to provide an <code>&lt;input&gt;</code> control outside of a <code>&lt;form&gt;</code> element. The <code>&lt;input&gt;</code> will not succeed in providing data to the server without the help of JavaScript, but that&#8217;s not a problem in an application using XHR.</p>

<p>But do <code>&lt;form&gt;</code> elements provide anything to users? When users of screen readers like JAWS or NVDA encounter a <code>&lt;form&gt;</code> element, they are automatically entered into a special interaction mode variously called &#8220;forms mode&#8221; or &#8220;application mode&#8221;. In this mode, some keystrokes that would otherwise be used as special shortcuts are switched off, allowing the user to interact with the form fields fully.</p>

<p>Fortunately, most input types — including <code>type="text"</code> here — trigger forms mode themselves, on focus. For instance, if I were to type <kbd>h</kbd> in the pictured input, it would enter &#8220;h&#8221; into the field, rather than navigating me to the nearest heading element.</p>

<p>The real reason we need a <code>&lt;form&gt;</code> element is because we&#8217;ll want to allow users to submit on <kbd>Enter</kbd>, and this only works reliably where a <code>&lt;form&gt;</code> contains the input upon which <kbd>Enter</kbd> is being pressed. The presence of the <code>&lt;form&gt;</code> is not just for code organization, or semantics, but affects browser behavior.</p>

<pre><code>&lt;form&gt;
  &lt;input type="text" placeholder="E.g. Adopt an owl"&gt;
  &lt;button type="submit"&gt;Add&lt;/button&gt;
&lt;/form&gt;
</code></pre>

<p></p>

<p>(<strong>Note:</strong> <a href="https://twitter.com/LeonieWatson">Léonie Watson</a> reports that <code>range</code> inputs are non-functional in Firefox + JAWS unless a <code>&lt;form&gt;</code> is employed or forms mode is entered manually, by the user.)</p>

<h3 id="labeling">Labeling</h3>

<p>Can you spot the deliberate mistake in the above code snippet? The answer is: I haven&#8217;t provided a label. Only a <code>placeholder</code> is provided and placeholders are intended for supplementary information only, such as the &#8220;adopt an owl&#8221; suggestion.</p>

<p>Placeholders are not reliable as labeling methods in assistive technologies, so another method must be provided. The question is: should that label be visible, or only accessible by screen reader?</p>

<p>In <em>almost</em> all cases, a visible label should be placed above or to the left of the input. Part of the reason for this is that placeholders disappear on focus and can be eradicated by autocomplete behavior, meaning sighted users lose their labels. Filling out information or correcting autocompleted information becomes guesswork. </p>

<p><img src="https://inclusive-components.design/content/images/2017/04/erm.svg" alt="An unlabeled field. The user has forgotten what they are doing and just entered 'erm'."></p>

<p>However, ours is a bit of a special case because the &#8220;add&#8221; label for the adjacent button is quite sufficient. Those looking at the form know what the input does thanks to the button alone.</p>

<p><strong>All inputs should have labels</strong>, because screen reader users don&#8217;t know to look ahead in the source to see if the submit button they&#8217;ve yet to reach gives them any clues about the form&#8217;s purpose. But simple input/submit button pairs like this and search regions can get away without <em>visible</em> labels. That is, so long as the submit button&#8217;s label is sufficiently descriptive.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/04/button_label_examples.svg" alt="Three examples of the described pattern. The first, fom our todo list, uses an add label for the submit button and is fine. The second example for a search form uses a submit button with search as the label and is also acceptable. The third example has a submit button with just submit as the label and is not advised.">
  <figcaption>In addition, make sure forms with multiple fields have visible labels for each field. Otherwise the user does not know which field is for what.</figcaption>
</figure>

<p>There are a number of ways to provide an invisible label to the input for screen reader users. One of the simpler and least verbose is <code>aria-label</code>. In the following example, &#8220;Write a new todo item&#8221; is the value. It&#8217;s a bit more descriptive than just &#8220;add&#8221;, which also helps to differentiate it from the button label, avoiding confusion when focus is moved between the two elements.</p>

<pre><code>&lt;form&gt;
  &lt;input type="text" aria-label="Write a new todo item" placeholder="E.g. Adopt an owl"&gt;
  &lt;button type="submit"&gt;Add&lt;/button&gt;
&lt;/form&gt;
</code></pre>

<aside>  
<h4>Placeholder styling</h4>  
<p>Be aware that some user agents (browsers) provide very feint placeholder text, in grey, which can lead to a failure under <a href="https://www.w3.org/TR/WCAG20/#visual-audio-contrast">WCAG 1.4.3 Contrast (Minimum)</a>.</p>  
<p>I recommend you style placeholders to have a higher contrast cross-browser and use an additional style — such as italicization in the pictured example — to help differentiate it from user-entered text.</p>  


<pre><code>::-webkit-input-placeholder { 
  color: #444;
  font-style: italic;
}
::-moz-placeholder { 
  color: #444;
  font-style: italic;
}
:-ms-input-placeholder { 
  color: #444;
  font-style: italic;
}
:-moz-placeholder { 
  color: #444;
  font-style: italic;
}
</code></pre>
<p>The independent blocks are regrettably necessary because each browser has trouble parsing other browsers&#8217; proprietary selectors.</p>  
</aside>

<h3 id="submissionbehavior">Submission behavior</h3>

<p>One of the advantages of using a <code>&lt;form&gt;</code> with a button of the <code>submit</code> <code>type</code> is that the user can submit by pressing the button directly, or by hitting <kbd>Enter</kbd>. Even users who do not rely exclusively on the keyboard to operate the interface may like to hit <kbd>Enter</kbd> because it&#8217;s quicker. What makes interaction possible for some, makes it better for others. That&#8217;s inclusion.</p>

<p>If the user tries to submit an invalid entry we need to stop them. By disabling the <code>&lt;button&gt;</code> until the input is valid, submission by click or by <kbd>Enter</kbd> is suppressed. In fact, the <code>type="submit"</code> button stops being focusable by keyboard. In addition to disabling the button, we provide <code>aria-invalid="true"</code> to the input. Screen readers will tell their users the input is invalid, letting them know they need to change it.</p>

<pre><code>&lt;form&gt;
  &lt;input type="text" aria-invalid="true" aria-label="Write a new todo item" placeholder="E.g. Adopt an owl"&gt;
  &lt;button type="submit" disabled&gt;Add&lt;/button&gt;
&lt;/form&gt;
</code></pre>

<h3 id="feedback">Feedback</h3>

<p>The deal with human-computer interaction is that when one party does something, the other party should respond. It&#8217;s only polite. For most users, the response on the part of the computer to adding an item is implicit: they simply see the item being added to the page. If it&#8217;s possible to <em>animate</em> the appearance of the new item, all the better: Some movement means its arrival is less likely to be missed.</p>

<p>For users who are not sighted or are not using the interface visually, nothing would seem to happen. They remain focused on the input, which offers nothing new to be announced in screen reader software. Silence.</p>

<p>Moving focus to another part of the page — the newly added todo, say — would cause that element to be announced. But we don&#8217;t want to move the user&#8217;s focus because they might want to forge ahead writing more todos. Instead we can use a live region.</p>

<h4 id="thefeedbackliveregion">The feedback live region</h4>

<p>Live regions are elements that tell screen readers to announce their contents <em>whenever those contents change</em>. With a live region, we can make screen readers talk to their users without making those users perform any action (such as moving focus).</p>

<p>Basic live regions are defined by <code>role="status"</code> or the equivalent <code>aria-live="polite"</code>. To maximize compatibility with different screen readers, you should use both. It may feel redundant, but it increases your audience.</p>

<pre><code>&lt;div role="status" aria-live="polite"&gt;
  &lt;!-- add content to hear it spoken --&gt;
&lt;/div&gt;
</code></pre>

<p></p>

<p>On the submit event, I can simply append the feedback to the live region and it will be immediately announced to the screen reader user.</p>

<pre><code>var todoName = document.querySelector('[type="text"]').value;

function addedFeedback(todoName) {
  let liveRegion = document.querySelector('[role="status"]');
  liveRegion.textContent = `${todoName} added.`;
}

// example usage
addedFeedback(todoName);
</code></pre>

<p>One of the simplest ways to make your web application more accessible is to wrap your status messages in a live region. Then, when they appear visually, they are also announced to screen reader users.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/04/adopt_status-1.svg" alt="Adopt an owl added status message. White text on green background prefixed by a tick icon">
  <figcaption>It&#8217;s conventional to color code status messages. This &#8220;success&#8221; message is green, for example. But it&#8217;s important to not rely on color, lest you let down color blind users. Hence, a supplemental tick icon is provided.</figcaption>
</figure>

<p>Inclusion is all about different users getting an <strong>equivalent experience</strong>, not necessarily the same experience. Sometimes what works for one user is meaningless, redundant, or obstructive to another. </p>

<p>In this case, the status message is not really needed visually because the item can be seen joining the list. In fact, adding the item to the list and revealing a status message at the same time would be to pull the user&#8217;s attention in two directions. In other words: the visible appending of the item and the announcement of &#8220;[item name] added&#8221; are already equivalent.</p>

<p>In which case, we can hide this particular messaging system from view, with a <code>vh</code> (visually hidden) class.</p>

<pre><code>&lt;div role="status" aria-live="polite" class="vh"&gt;
  &lt;!-- add content to hear it spoken --&gt;
&lt;/div&gt;
</code></pre>

<p>This utility class uses some magic to make sure the element(s) in question are not visible or have layout, but are still detected and announced in screen readers. Here&#8217;s what it looks like:</p>

<pre><code>.vh {
    position: absolute !important;
    clip: rect(1px, 1px, 1px, 1px);
    padding:0 !important;
    border:0 !important;
    height: 1px !important;
    width: 1px !important;
    overflow: hidden;
}
</code></pre>

<h2 id="checkingofftodoitems">Checking off todo items</h2>

<p>Unlike in the previous <a href="https://inclusive-components.club/toggle-button/">toggle button</a> post, this time checkboxes feel like the semantically correct way to activate and deactivate. You don&#8217;t <em>press</em> or <em>switch off</em> todo items; you <em>check them off</em>.</p>

<p>Lucky, checkboxes let us do that with ease — the behavior comes out-of-the-box. We just need to remember to label each instance. When iterating over the checkbox data, we can write unique values to each <code>for</code>/<code>id</code> pairing using a for loop&#8217;s current index and string interpolation. Here&#8217;s how it can be done in Vue.js:</p>

<pre><code>&lt;ul&gt;
  &lt;li v-for="(todo, index) in todos"&gt;
    &lt;input type="checkbox" :id="`todo-${index}`" v-model="todo.done"&gt; 
    &lt;label :for="`todo-${index}`"&gt;{{todo.name}}&lt;/label&gt;     
  &lt;/li&gt;
&lt;/ul&gt;
</code></pre>

<p>(<strong>Note:</strong> In this example, we imagine that each todo has a <code>done</code> property, hence <code>v-model="todo.done"</code> which automatically checks the checkbox where it evaluates as true.)</p>

<h3 id="thelinethroughstyle">The line-through style</h3>

<p>Making robust and accessible components is easy when you use semantic elements as they were intended. In my version, I just add a minor enhancement: a <code>line-through</code> style for checked items. This is applied to the <code>&lt;label&gt;</code> via the <code>:checked</code> state using an adjacent sibling combinator.</p>

<pre><code>:checked + label {
  text-decoration: line-through;
}
</code></pre>

<p>Once again, I&#8217;m leveraging implicit state to affect style. No need for adding and removing <code>class="crossed-out"</code> or similar.</p>

<p>(<strong>Note:</strong> If you want to style the checkbox controls themselves, <a href="http://wtfforms.com/">WTF Forms</a> gives guidance on doing so without having to create custom elements. In the <a href="https://codepen.io/heydon/pen/VpVNKW">demo</a> at the end of this article, I use a proxy <code>.tick</code> <code>&lt;span&gt;</code> to do something similar.)</p>

<h2 id="deletingtodoitems">Deleting todo items</h2>

<p>Checking off and deleting todo list items are distinct actions. Because sometimes you want to see which items you&#8217;ve done, and sometimes you add todo items to your list that you didn&#8217;t mean to, or which become non-applicable.</p>

<p>The functionality to delete todos can be provided via a simple button. No need for any special state information — the label tells us everything we need to know. Of course, if the button uses an icon image or font glyph in place of an interpretable text node, an auxiliary label should be provided.</p>

<pre><code>&lt;button aria-label="delete"&gt;
  &amp;times;
&lt;/button&gt;
</code></pre>

<p>In fact, let&#8217;s be more specific and include the todo item&#8217;s name. It&#8217;s always better to provide labels which make sense in isolation. This unique label helps differentiate it from the others. Your JavaScript framework of choice should provide a templating facility to achieve this. In my choice, Vue.js, it looks like this:</p>

<pre><code>&lt;button :aria-label="`delete ${todo.name}`"&gt;
  &amp;times;
&lt;/button&gt;
</code></pre>

<p>In this example, <code>&amp;times;</code> is used to represent a cross symbol. Were it not for the <code>aria-label</code> overriding it, the label would be announced as &#8220;times&#8221; or &#8220;multiplication&#8221;  depending on the screen reader in question. </p>

<p>Always be wary of how screen readers interpret special unicode characters and symbols. Sometimes, arguably, they are quite helpful, like the down arrow in our empty state message. This will be interpreted as &#8220;down pointing arrow&#8221; or similar. Since, in our case, the text input is always below the list both visually and in source order, the arrow guides the user toward it.</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/just_empty-1.svg" alt="The empty state, reading either you've done everything already or there are still things to add to your list. Add your first todo, down pointing arrow. The text input and add button appear below."></p>

<p>In our case, a dustbin icon is provided using SVG. SVG is great because it&#8217;s an image format that scales without degrading. Many kinds of users often feel the need to scale/zoom interfaces, including the short-sighted and those with motor impairments who are looking to create larger touch or click targets.</p>

<pre><code>&lt;button aria-label="delete"&gt;
  &lt;svg&gt;
    &lt;use xlink:href="#bin-icon"&gt;&lt;/use&gt;
  &lt;/svg&gt;
&lt;/button&gt;
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/04/just_the_list.svg" alt="Three todo list items, each with a dustbin icon to their right for deleting them."></p>

<p>To reduce bloat when using multiple instances of the same inline SVG icon, we employ the <code>&lt;use&gt;</code> element, which refers to a canonical version of the SVG, defined as a <code>&lt;symbol&gt;</code> at the head of the document body:</p>

<pre><code>&lt;body&gt;
  &lt;svg style="display: none"&gt;
    &lt;symbol id="bin-icon" viewBox="0 0 20 20"&gt;
      &lt;path d="[path data here]"&gt;
    &lt;/symbol&gt;
  &lt;/svg&gt;
</code></pre>

<p>A bloated DOM can diminish the experience of many users since many operations will take longer. Assistive technology users especially may find their software unresponsive.</p>

<aside>  
  <h3>Inclusive icons</h3>
  <p>The enhanced <a href="http://uxmyths.com/post/715009009/myth-icons-enhance-usability">usability offered to interfaces by icons is contested</a>. Certainly, in combination with text, they can help comprehension — especially for those who have low literacy or who are not reading the interface in their first language. However, any icons offered without supplementary text risk being misapprehended.</p>
<img src="https://inclusive-components.design/content/images/2017/04/bin_and_cross.svg" alt="A dustbin icon placed next to a cross icon for comparison">
<p>Does my dustbin icon really say <em>delete</em>? Could I make a better icon, which looks more like a dustbin? I could try something different, like using a cross icon (as in TodoMVC&#8217;s implementation) but isn&#8217;t that more associated with a <em>closing</em> action? There are no easy answers, so testing with real users is your best bet.</p>  
<p>Fortunately, the accidental deletion of a todo item is not really a critical mistake, so users can safely find out what the icon means through trial and error. Where deletion <em>is</em> critical, a confirmation dialog should be provided, acting as both an explanation and a means to complete the action.</p>  
<img src="https://inclusive-components.design/content/images/2017/04/dialog.svg" alt="Dialog reading &#8216;are you sure you want to delete this item&#8217; with yes and cancel buttons">
</aside>

<h3 id="focusmanagement">Focus management</h3>

<p>When a user clicks the delete button for a todo item, the todo item — including the checkbox, the label, and <strong>the delete button itself</strong> — will be remove from the DOM. This raises an interesting problem: what happens to focus when you delete the currently focused element?</p>

<p><img src="https://inclusive-components.design/content/images/2017/04/focus_destroyed.svg" alt="The first picture shows the Learn Haskell todo item's bin icon/delete button focused with a blue ring. The second picture shows that todo item removed from the list and focus is nowhere to be seen."></p>

<p>Unless you&#8217;re careful, the answer is <em>something very annoying</em> for keyboard users, including screen reader users.</p>

<p>The truth is, browsers don&#8217;t know where to place focus when it has been destroyed in this way. Some maintain a sort of &#8220;ghost&#8221; focus where the item used to exist, while others jump to focus the next focusable element. Some flip out completely and default to focusing the outer document — meaning keyboard users have to crawl through the DOM back to where the removed element was. </p>

<p>For a consistent experience between users, we need to be deliberate and <code>focus()</code> an appropriate element, but which one?</p>

<p>One option is to focus the first checkbox of the list. Not only will this announce the checkbox&#8217;s label and state, but also the total number of list items remaining: one fewer than a moment ago. All useful context.</p>

<pre><code>document.querySelector('ul input').focus();
</code></pre>

<p>(<strong>Note:</strong> <code>querySelector</code> returns the <em>first</em> element that matches the selector. In our case: the first checkbox in the todo list.)</p>

<p>But what if we just deleted the last todo item in our list and had returned to the empty state? There&#8217;s no checkbox we can focus. Let&#8217;s try something else. Instead, I want to do two things:</p>

<ol>  
<li>Focus the region&#8217;s &#8220;My Todo List&#8221; heading</li>

<li>Use the live region already instated to provide some feedback</li>  
</ol>

<p>You should never make non-interactive elements like headings focusable by users because the expectation is that, if they&#8217;re focusable, they should actually <em>do</em> something. When I&#8217;m testing an interface and there are such elements, I would therefore fail it under <a href="https://www.w3.org/TR/WCAG20/#navigation-mechanisms">WCAG 2.4.3 Focus Order</a>.</p>

<p>However, sometimes you need to direct a user to a certain part of the page, via a script. In order to move a user to a heading and have it announced, you need to do two things:</p>

<ol>  
<li>Provide that heading with <code>tabindex="-1"</code></li>

<li>Focus it using the <code>focus()</code> method in your script</li>  
</ol>

<pre><code>&lt;h1 tabindex="-1"&gt;My Todo List&lt;/h1&gt;
</code></pre>

<p>The <code>-1</code> value&#8217;s purpose is twofold: it makes elements unfocusable by users (including normally focusable elements) but makes them focusable by JavaScript. In practice, we can move a user to an inert element without it becoming a &#8220;tab stop&#8221; (an element that can be moved to via the <kbd>Tab</kbd> key) among focusable elements within the page. </p>

<p>In addition, focusing the heading will announce its text, role, level, and (in some screen readers) contextual information such as &#8220;region&#8221;. At the very least, you should hear <em>&#8220;My Todo List, heading, level 2&#8221;</em>. Because it is in focus, pressing tab will step the user back inside the list and onto the first checkbox. In effect, we&#8217;re saying, <em>&#8220;now that you&#8217;ve deleted that list item, here&#8217;s the list again.&#8221;</em></p>

<p>I typically do not supply focus styles to elements which are focused programmatically in this way. Again, this is because the target element is not interactive and should not appear to be so.</p>

<pre><code>[tabindex="-1"] { outline: none }
</code></pre>

<p>After the focused element (and with it its focus style) has been removed, the heading is focused. A keyboard user can then press Tab to find themselves on that first checkbox or — if there are no items remaining — the text input at the foot of the component.</p>

<h4 id="thefeedback">The feedback</h4>

<p>Arguably, we&#8217;ve provided enough information for the user and placed them in a perfect position to continue. But it&#8217;s always better to be explicit. Since we already have a live region instated, why not use that to tell them the item has been successfully removed?</p>

<pre><code>function deletedFeedback(todoName) {
  let liveRegion = document.querySelector('[role="status"]');
  liveRegion.textContent = `${todoName} deleted.`;
}

// example usage
deletedFeedback(todoName);
</code></pre>

<p>I appreciate that you probably wouldn&#8217;t be writing this in vanilla JavaScript, but this is basically how it would work.</p>

<p>Now, because we&#8217;ve used <code>role="status"</code> (<code>aria-live="polite"</code>), something neat happens in supporting screen readers: <em>&#8220;My Todo List, heading, level 2&#8221;</em> is read first, followed by <em>&#8220;[todo item name] deleted&#8221;</em>. </p>

<p>That&#8217;s because <em>polite</em> live regions wait until the interface and the user have settled before making themselves known. Had I used <code>role="alert"</code> (<code>aria-live="assertive"</code>), the status message would override (or partially override) the focus-invoked heading announcement. Instead, the user knows both where they are, and that what they&#8217;ve tried to do has succeeded.</p>

<h2 id="workingdemo">Working demo</h2>

<p>I&#8217;ve created a <a href="https://codepen.io/heydon/pen/VpVNKW/">codePen page</a> to demonstrate the techniques in this post. It uses Vue.js, but could have been created with any JavaScript framework. It&#8217;s offered for testing with different screen reader and browser combinations.</p>

<iframe height="265" scrolling="no" title="Vue.js TODO List " src="//codepen.io/heydon/embed/VpVNKW/?height=265&theme-id=0&default-tab=html,result&embed-version=2" frameborder="no" allowtransparency="true" allowfullscreen="true" style="width: 100%;">See the Pen <a href="https://codepen.io/heydon/pen/VpVNKW/">Vue.js TODO List </a> by Heydon (<a href="http://codepen.io/heydon">@heydon</a>) on <a href="http://codepen.io">CodePen</a>.  
</iframe>

<h2 id="conclusion">Conclusion</h2>

<p>Counting semantic structure, labeling, iconography, focus management and feedback, there&#8217;s quite a lot to consider when creating an inclusive todo list component. If that makes inclusive design seem dauntingly complex, consider the following:</p>

<ol>  
<li>This is new stuff. Don&#8217;t worry, it&#8217;ll become second nature soon enough.</li>

<li>Everything you&#8217;ve learned here is applicable to a wide range of content management components, and many other components.</li>

<li>You only need to build a rock solid component once. Then it can live in your pattern library and be reused indefinitely.</li>  
</ol>

<h3 id="checklist">Checklist</h3>

<ul>  
<li>Give every major component, like this one, a well-written heading.</li>

<li>Only provide &#8220;screen reader only&#8221; input labels if something else labels the input visually. Placeholders don&#8217;t count.</li>

<li>When you remove a focused element from the DOM, focus an appropriate nearby element with <code>focus()</code>.</li>

<li>Consider the wording of empty states carefully. They introduce new users to your functionality.</li>  
</ul>]]></content:encoded></item><item><title><![CDATA[Toggle Buttons]]></title><description><![CDATA[<p>Some things are either on or off and, when those things aren&#8217;t on  
(or off), they are invariably off (or on). The concept is so rudimentary
 that I&#8217;ve only complicated it by trying to explain it, yet on/off 
switches (or toggle buttons) are not all</p>]]></description><link>https://inclusive-components.design/toggle-button/</link><guid isPermaLink="false">cbc29a26-64cc-496d-a87f-9c7bf8d391e9</guid><dc:creator><![CDATA[Heydon Pickering]]></dc:creator><pubDate>Fri, 31 Mar 2017 13:33:28 GMT</pubDate><content:encoded><![CDATA[<p>Some things are either on or off and, when those things aren&#8217;t on  
(or off), they are invariably off (or on). The concept is so rudimentary
 that I&#8217;ve only complicated it by trying to explain it, yet on/off 
switches (or toggle buttons) are not all alike. Although their purpose  
is simple, their applications and forms vary greatly. </p>

<p>In this inaugural post, I&#8217;ll be exploring what it takes to  make  
toggle buttons inclusive. As with any component, there&#8217;s no one way to  
go about this, especially when such controls are examined under  
different contexts. However, there&#8217;s certainly plenty to forget to do or  
 to otherwise screw up, so let&#8217;s try to avoid any of that.</p>

<hr>

<h2 id="changingstate">Changing state</h2>

<p>If a web application did not change according to the instructions of  
its user, the resulting experience would be altogether unsatisfactory.  
Nevertheless, the luxury of being able to make web documents augment  
themselves instantaneously, without recourse to a page refresh, has not  
always been present.</p>

<p>Unfortunately, somewhere along the way we decided that accessible web  
 pages were only those where very little happened — static documents, 
designed purely to be read. Accordingly, we made little effort to make  
the richer, <em>stateful</em> experiences of web applications inclusive. </p>

<p>A popular misconception has been that screen readers <em>don&#8217;t understand</em>  
 JavaScript. Not only is this entirely untrue — all major screen readers
 react to changes in the DOM as they occur — but basic state changes, 
communicated both visually and to assistive technology software, do not  
necessarily depend on JavaScript to take place anyway.</p>

<h2 id="checkboxesandradiobuttons">Checkboxes and radio buttons</h2>

<p>Form elements are the primitives of interactive web pages and, where  
we&#8217;re not employing them directly, we should be paying close attention  
to how they behave. Their handling of state changes have established  
usability conventions we would be foolish to ignore.</p>

<p>Arguably, an out-of-the-box input of the <code>checkbox</code> type  
is a perfectly serviceable on/off switch all its own. Where  labelled  
correctly, it has all the fundamental ingredients of an accessible  
control: it&#8217;s screen reader and keyboard accessible between platforms  
and devices, and it communicates its change of state (<em>checked</em> to <em>unchecked</em> or vice versa) without needing to rebuild the entire document.</p>

<p>In the following example, a checkbox serves as the toggle  for an email notifications setting.</p>

<pre><code>&lt;input type="checkbox" id="notify" name="notify" value="on"&gt;  
&lt;label for="notify"&gt;Notify by email&lt;/label&gt;  
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/03/checkbox.svg" alt="The notify my email control with checkbox checked"></p>

<p>Screen reader software is fairly uniform in its interpretation of this control. On focusing the control (moving to it using the <kbd>Tab</kbd> key) something similar to, <em>&#8220;Notify by email, checkbox, unchecked&#8221;</em> will be announced. That&#8217;s the label, role, and state information all present.</p>

<p>On checking the checkbox, most screen reader software will announce  
the changed state, &#8220;checked&#8221; (sometimes repeating the label and role  
information too), immediately. Without JavaScript, we&#8217;ve handled state  
and screen reader software is able to feed back to the user.</p>

<aside>  
<h3>Screen readers are not just for the blind</h3>  
<p>Some operate screen readers to assist their understanding of an  
interface. Others may be visually dyslexic or have low literacy. There  
are even those who have little physical or cognitive trouble  
understanding an interface who simply prefer to have it read out to them  
 sometimes.</p>

<p><strong>Supporting screen reader software is supporting screen reader software, not blind people</strong>. Screen readers are a tool a lot of different people like to use.</p>  
</aside>

<p>In this case, the on/off part of the switch is not communicated by  
the label but the state. Instead, the label is for identifying the thing  
 that we are turning off or on. Should research show that users benefit 
from a more explicit on/off metaphor, a radio button group can be  
employed.</p>

<pre><code>&lt;fieldset&gt;  
  &lt;legend&gt;Notify by email&lt;/legend&gt;
  &lt;input type="radio" id="notify-on" name="notify" value="on" checked&gt;
  &lt;label for="notify-on"&gt;on&lt;/label&gt;
  &lt;input type="radio" id="notify-off" name="notify" value="off"&gt;
  &lt;label for="notify-off"&gt;off&lt;/label&gt;
&lt;/fieldset&gt;  
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/03/radio.svg" alt="Fieldset with notify by email group label (legend) and radio buttons labeled on and off. The on one is selected."></p>

<p>Group labels are a powerful tool. As their name suggests, they can  
provide a single label to related (grouped) items. In this case, the <code>&lt;fieldset&gt;</code> group element works together with the <code>&lt;legend&gt;</code> element to provide the group label &#8220;Notify by email&#8221; to the pair of radio buttons. These buttons are made a pair by sharing a <code>name</code>  
 attribute value, which makes it possible to toggle between them using 
your arrow keys. HTML semantics don&#8217;t just add information but also  
affect behavior.</p>

<p>In the Windows screen readers JAWS and NVDA, when the user focuses  
the first control, the group label is prepended to that control&#8217;s  
individual label and the grouped radio buttons are enumerated. In NVDA,  
the term &#8220;grouping&#8221; is appended to make things more explicit. In the  
above example, focusing the first (checked by default) radio button  
elicits, <em>&#8220;Notify by email, grouping, on radio button, checked, one of two&#8221;</em>.</p>

<p>Now, even though the checked state (announced as &#8220;selected&#8221; in some  
screen readers) is still being toggled, what we&#8217;re really allowing the  
user to do it switch between &#8220;on&#8221; and &#8220;off&#8221;. Those are the two possible <em>lexical states</em>, if you will, for the composite control.</p>

<aside>  
<h3>Styling form elements</h3>  
<p>Form elements are notoriously hard to style, but there are  
well-supported CSS techniques for styling radio and checkbox controls,  
as I wrote in <em><a href="https://www.sitepoint.com/replacing-radio-buttons-without-replacing-radio-buttons/">Replacing Radio Buttons Without Replacing Radio Buttons</a></em>. For tips on how to style select elements and file inputs, consult <em><a href="http://wtfforms.com/">WTF Forms?</a></em> by Mark Otto.</p>  
</aside>

<h3 id="thisdoesntquitefeelright">This doesn&#8217;t quite feel right</h3>

<p>Both the checkbox and radio button implementations are tenable as  
on/off controls. They are, after all, accessible by mouse, touch,  
keyboard, and assistive technology software across different devices,  
browsers, and operating systems.</p>

<p>But accessibility is only a part of inclusive design. These controls also have to <em>make sense</em> to users; they have to play an unambiguous role within the interface.</p>

<p>The trouble with using form elements is their longstanding  
association with the collection of data. That is, checkboxes and radio  
buttons are established as controls for designating <em>values</em>. When a user checks a checkbox, they may just be switching a state, but they may <em>suspect</em> they are also choosing a value for submission. </p>

<p>Whether you&#8217;re a sighted user looking at a checkbox, a screen reader  
user listening to its identity being announced, or both, its etymology  
is problematic. We expect toggle buttons to be buttons, but checkboxes  
and radio buttons are really inputs.</p>

<h2 id="atruetogglebutton">A true toggle button</h2>

<p>Sometimes we use <code>&lt;button&gt;</code> elements to submit forms. To be fully compliant and reliable these buttons should take the <code>type</code> value of <code>submit</code>.</p>

<pre><code>&lt;button type="submit"&gt;Send&lt;/button&gt;  
</code></pre>

<p>But these are only one variety of button, covering one use case. In truth, <code>&lt;button&gt;</code> elements can be used for all sorts of things, and not just in association with forms. They&#8217;re just <em>buttons</em>. We remind ourselves of this by giving them the <code>type</code> value of <code>button</code>.</p>

<pre><code>&lt;button type="button"&gt;Send&lt;/button&gt;  
</code></pre>

<p>The generic button is your go-to element for changing anything within  
 the interface (using JavaScript and without reloading the page) except 
one&#8217;s location within and between documents, which is the purview of  
links. </p>

<p>Next to links, buttons should be the interactive element you use most  
 prolifically in web applications. They come prepackaged with the 
&#8220;button&#8221; role and are keyboard and screen reader accessible by default. 
Unlike some form elements, they are also trivial to style.</p>

<p>So how do we make a <code>&lt;button&gt;</code> a toggle button? It&#8217;s  
 a case of using WAI-ARIA as a progressive enhancement. WAI-ARIA offers 
states that are not available in basic HTML, such as the <em>pressed</em>  
 state. Imagine a power switch for a computer. When it&#8217;s pressed — or 
pushed in — that denotes the computer is in its &#8220;on&#8221; state. When it&#8217;s  
unpressed — poking out — the computer must be off.</p>

<pre><code>&lt;button type="button" aria-pressed="true"&gt;  
  Notify by email
&lt;/button&gt;  
</code></pre>

<p>WAI-ARIA state attributes like <code>aria-pressed</code> behave like booleans but, unlike standard HTML state attributes like <code>checked</code> they must have an explicit value of <code>true</code> or <code>false</code>. Just adding <code>aria-pressed</code> is not reliable. Also, the absence of the attribute would mean the <em>unpressed</em> state would not be communicated (a button without the attribute is just a generic button).</p>

<p>You can use this control inside a form, or outside, depending on your needs. But if you do use it inside a form, the <code>type="button"</code> part is important. If it&#8217;s not there, some browsers will default to an implicit <code>type="submit"</code> and try to submit the form. You don&#8217;t have to use <code>event.preventDefault()</code> on <code>type="button"</code> controls to suppress form submission.</p>

<p>Switching the state from <code>true</code> (on) to <code>false</code> (off) can be done via a simple click handler. Since we are using a <code>&lt;button&gt;</code>, this event type can be triggered with a mouse click, a press of either the <kbd>Space</kbd> or <kbd>Enter</kbd> keys, or by tapping the button through a touch screen. Being responsive to each of these actions is something built into <code>&lt;button&gt;</code> elements as standard. If you consult the <a href="https://developer.mozilla.org/en/docs/Web/API/HTMLButtonElement">HTMLButtonElement</a> interface, you&#8217;ll see that other properties, such as <code>disabled</code>, are also supported out-of-the-box. Where <code>&lt;button></code> elements are not used, these behaviors have to be emulated with bespoke scripting.</p>

<pre><code>const toggle = document.querySelector('[aria-pressed]');

toggle.addEventListener('click', (e) =&gt; {  
  let pressed = e.target.getAttribute('aria-pressed') === 'true';
  e.target.setAttribute('aria-pressed', String(!pressed));
});
</code></pre>

<h3 id="aclearerstate">A clearer state</h3>

<p>An interesting thing happens when a button with the <code>aria-pressed</code>  
 state is encountered by some screen readers: it is identified as a 
&#8220;toggle button&#8221; or, in some cases, &#8220;push button&#8221;. The presence of the 
state attribute changes the button&#8217;s identity.</p>

<p>When focusing the example button with <code>aria-pressed="true"</code> using NVDA, the screen reader announces, <em>&#8220;Notify by email, toggle button, pressed&#8221;</em>.  
 The &#8220;pressed&#8221; state is more apt than &#8220;checked&#8221;, plus we eschew the form data input  connotations. When the button is clicked, 
immediate feedback is offered in the form of <em>&#8220;not pressed&#8221;</em>.</p>

<h3 id="styling">Styling</h3>

<p>The HTML we construct is an important part of the design work we do  
and the things we create for the web. I&#8217;m a strong believer in doing  
HTML First Prototyping™, making sure there&#8217;s a solid foundation for the  
styled and branded product. </p>

<p>In the case of our toggle button, this foundation includes  the  
semantics and behavior to make the button interoperable with various  
input (e.g. voice activation software) and output (e.g. screen reader)  
devices. That&#8217;s possible using HTML, but CSS is needed to make the  
control understandable visually.</p>

<p>Form should follow function, which is simple to achieve in CSS:  
everything in our HTML that makes our simple toggle button function can  
also be used to give it form.</p>

<ul>  
<li><code>&lt;button&gt;</code> → <code>button</code> element selector</li>  
<li><code>aria-pressed="true"</code> → <code>[aria-pressed="true"]</code> attribute selector</li>  
</ul>

<p>In a consistent and, therefore, easy to understand interface, buttons  
 should share a certain look. Buttons should all look like buttons. So, 
our basic toggle button styles should probably inherit from the <code>button</code> element block:</p>

<pre><code>/* For example... */
button {  
  color: white;
  background-color: #000;
  border-radius: 0.5rem;
  padding: 1em 2em;
}
</code></pre>

<p>There are a number of ways we could visually denote &#8220;pressed&#8221;. Interpreted literally, we might make the button look <em>pressed in</em> using some inset <code>box-shadow</code>. Let&#8217;s employ an attribute selector for this:</p>

<pre><code>[aria-pressed="true"] {
  box-shadow: inset 0 0 0 0.15rem #000, 
              inset 0.25em 0.25em 0 #fff;
}
</code></pre>

<p>To complete the pressed/unpressed metaphor, we can use some positioning and <code>box-shadow</code> to make the unpressed button &#8220;poke out&#8221;. This block should appear above the <code>[aria-prressed="true"]</code> block in the cascade.</p>

<pre><code>[aria-pressed] {
  position: relative;
  top: -0.25rem;
  left: -0.25rem;
  box-shadow: 0.125em 0.125em 0 #fff, 
              0.25em 0.25em #000;
}
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/03/pressed_unpressed.svg" alt="Left button, sticking out, is labeled aria-pressed equals false. Right button, visually depressed, is labelled aria-pressed equals true."></p>

<p>(<strong>Note:</strong> This styling method is offered just as one idea. You may find that something more explicit, like the use of "on"/"off" labels in an example to follow,  is better understood by more users.)</p>

<aside>  
<h3>Don&#8217;t rely on color alone</h3>  
<p>&#8220;On&#8221; is often denoted by a green color, and &#8220;off&#8221; by red. This is a  
well-established convention and there&#8217;s no harm in incorporating it.  
However, be careful not to *only* use color to describe the button&#8217;s two  
 states. If you did, some color blind users would not be able to 
differentiate them.</p>  
<figure>  
<img src="https://inclusive-components.design/content/images/2017/03/color_only.svg" alt="The aria-pressed false button has a red background color and the aria-pressed true button has a green background color">
<figcaption>These versions of the control would fail <a href="https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-without-color">WCAG 2.0 1.4.1 Use Of Color (Level A)</a></figcaption>  
</figure>  
</aside>

<h4 id="focusstyles">Focus styles</h4>

<p>It&#8217;s important buttons, along with <em>all</em> interactive  
components, have focus styles. Otherwise people navigating by keyboard  
cannot see which element is in their control and ready to be operated.</p>

<p>The best focus styles do not affect layout (the interface shouldn&#8217;t  
jiggle around distractingly when moving between elements). Typically,  
one would use <code>outline</code>, but <code>outline</code> only ever draws a box in most browsers. To fit a focus style around the curved corners of our button, a <code>box-shadow</code> is better. Since we are using <code>box-shadow</code> already, we have to be a bit careful: note the two comma-separated <code>box-shadow</code> styles in the pressed-and-also-focused state.</p>

<pre><code>/* Remove the default outline and 
add the outset shadow */  
[aria-pressed]:focus {
  outline: none;
  box-shadow: 0 0 0 0.25rem yellow;
}

/* Make sure both the inset and 
outset shadow are present */  
[aria-pressed="true"]:focus {
  box-shadow: 0 0 0 0.25rem yellow,
              inset 0 0 0 0.15rem #000, 
              inset 0.25em 0.25em 0 #fff;  
}
</code></pre>

<h2 id="changinglabels">Changing labels</h2>

<p>The previous toggle button design has a self-contained, unique label  
and differentiates between its two states using a change in attribution  
which elicits a style. What if we wanted to create a button that changes  
 its label from &#8220;on&#8221; to &#8220;off&#8221; or &#8220;play&#8221; to &#8220;pause&#8221;?</p>

<p>It&#8217;s perfectly easy to do this in JavaScript, but there are a couple of things we need to be careful about.</p>

<ol>  
<li>If the <em>label</em> changes, what happens with the state?  </li>  
<li>If the label is just &#8220;on&#8221; or &#8220;off&#8221; (&#8220;play&#8221; or &#8220;pause&#8221;; &#8220;active&#8221; or &#8220;inactive&#8221;) how do we know what the button actually controls?</li>  
</ol>

<p>In the previous toggle button example, the label described <em>what</em>  
 would be on or off. Where the &#8220;what&#8221; part is not consistent, confusion 
quickly ensues: once &#8220;off&#8221;/unpressed has become &#8220;on&#8221;/pressed, I have to  
unpress the &#8220;on&#8221; button to turn the &#8220;off&#8221; button back on. What?</p>

<p>As a rule of thumb, you should never change pressed state and label  
together. If the label changes, the button has already changed state in a  
 sense, just not via explicit WAI-ARIA state management.</p>

<p>In the following example, just the label changes.</p>

<pre><code>const button = document.querySelector('button');

button.addEventListener('click', (e) =&gt; {  
  let text = e.target.textContent === 'Play' ? 'Pause' : 'Play';
  e.target.textContent = text;
});
</code></pre>

<p>The problem with this method is that the label change is not  
announced as it happens. That is, when you click the play button,  
feedback equivalent to &#8220;pressed&#8221; is absent.  Instead, you have to  
unfocus and refocus the button manually to hear that it has changed. Not  
 an issue for sighted users, but less ergonomic for blind screen reader 
users.</p>

<p>Play/pause buttons usually switch between a play symbol (a triangle on its side) and a pause symbol (two vertical lines). We <em>could</em> do this while keeping a consistent non-visual label and changing state.</p>

<pre><code>&lt;!-- Paused state --&gt;  
&lt;button type="button" aria-pressed="false" aria-label="play"&gt;  
  &amp;#x25b6;
&lt;/button&gt;

&lt;-- Playing state --&gt;  
&lt;button type="button" aria-pressed="true" aria-label="play"&gt;  
  &amp;#x23f8;
&lt;/button&gt;  
</code></pre>

<p>Because <code>aria-label</code> overrides the unicode symbol text node, the paused button is announced as something similar to, <em>&#8220;Play button, not pressed&#8221;</em> and the playing button as ,<em>&#8220;Play button, pressed&#8221;</em>. </p>

<p>This works pretty well, except for where voice recognition and  
activation is concerned. In voice recognition software, you typically  
need to identify buttons by vocalizing their labels. And if a user sees a  
 pause symbol, their first inclination is to say &#8220;pause&#8221;, not &#8220;play&#8221;. For this reason, switching the label rather than the state is more robust here.</p>

<figure>  
<img src="https://inclusive-components.design/content/images/2017/03/play_pause.svg" alt="Three implementation examples. The first just changes label from play to pause and is okay. The second keeps the play label and changes state, which is incorrect because the pause button cannot be identified with voice recognition. The third changes label and state so the button becomes a pause button which is pressed, which is incorrect. Only use one of the first two implementations.">
<figcaption>Never change label and state at the same time. In this example, that would result in a paused button in the pressed state.  
Since the video or audio would be playing at this point, the lexical  
&#8220;pause&#8221; state cannot be also be considered &#8220;pressed&#8221; on &#8220;on&#8221;.</figcaption>  
</figure>

<h3 id="auxiliarylabeling">Auxiliary labeling</h3>

<p>In some circumstances, we may want to provide on/off switches which  
actually read &#8220;on/off&#8221;. The trick with these is making sure there is a  
clear association between each  toggle switch and a respective,  
auxiliary label.</p>

<p>Imagine the email notification setting is grouped alongside other  
similar settings in a list. Each list item contains a description of the  
 setting followed by an on/off switch. The on/off switch uses the terms 
&#8220;on&#8221; and &#8220;off&#8221; as part of its design. Some <code>&lt;span&gt;</code> elements are provided for styling.</p>

<pre><code>&lt;h2&gt;Notifications&lt;/h2&gt;  
&lt;ul&gt;  
  &lt;li&gt;
    Notify by email 
    &lt;button&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Notify by SMS 
    &lt;button&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Notify by fax 
    &lt;button&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Notify by smoke signal 
    &lt;button&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
&lt;/ul&gt;  
</code></pre>

<p><img src="https://inclusive-components.design/content/images/2017/03/notifications.svg" alt="A list of notifications settings with associated buttons reading with either on or off highlighted, depending on the state"></p>

<p>The virtue of lists is that, both visually and non-visually, they  
group items together, showing they are related. Not only does this help  
comprehension, but lists also provide navigational shortcuts in some  
screen readers. For example, JAWS provides the <kbd>L</kbd> (list) and <kbd>I</kbd> (list item) quick keys for moving between and through lists.</p>

<p>Each &#8216;label&#8217; and button is associated by belonging to a common list  
item. However, not providing an explicit, unique label is dangerous  
territory — especially where voice recognition is concerned. Using <code>aria-labelledby</code>, we can associate each button with the list&#8217;s text:</p>

<pre><code>&lt;h2&gt;Notifications&lt;/h2&gt;  
&lt;ul&gt;  
  &lt;li&gt;
    &lt;span id="notify-email"&gt;Notify by email&lt;/span&gt; 
    &lt;button aria-labelledby="notify-email"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-sms"&gt;Notify by SMS&lt;/span&gt;
    &lt;button aria-labelledby="notify-sms"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-fax"&gt;Notify by fax&lt;/span&gt;
    &lt;button aria-labelledby="notify-fax"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-smoke"&gt;Notify by smoke signal&lt;/span&gt; 
    &lt;button aria-labelledby="notify-smoke"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
&lt;/ul&gt;  
</code></pre>

<p>Each <code>aria-labelledby</code> value matches the appropriate span <code>id</code>, forming the association and giving the button its unique label. It works much like a <code>&lt;label&gt;</code> element&#8217;s <code>for</code> attribute identifying a field&#8217;s <code>id</code>.</p>

<h4 id="theswitchrole">The switch role</h4>

<p>Importantly, the ARIA label overrides each button&#8217;s textual content, meaning we can once again employ <code>aria-pressed</code> to communicate state. However, since these buttons are explicitly &#8220;on/off&#8221; switches, we can instead use the <a href="https://www.w3.org/TR/wai-aria-1.1/#switch">WAI-ARIA switch role</a>, which communicates state via <code>aria-checked</code>.</p>

<pre><code>&lt;h2&gt;Notifications&lt;/h2&gt;  
&lt;ul&gt;  
  &lt;li&gt;
    &lt;span id="notify-email"&gt;Notify by email&lt;/span&gt; 
    &lt;button role="switch" aria-checked="true" aria-labelledby="notify-email"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-sms"&gt;Notify by SMS&lt;/span&gt;
    &lt;button role="switch" aria-checked="true" aria-labelledby="notify-sms"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-fax"&gt;Notify by fax&lt;/span&gt;
    &lt;button role="switch" aria-checked="false" aria-labelledby="notify-fax"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;span id="notify-smoke"&gt;Notify by smoke signal&lt;/span&gt; 
    &lt;button role="switch" aria-checked="false" aria-labelledby="notify-smoke"&gt;
      &lt;span&gt;on&lt;/span&gt;
      &lt;span&gt;off&lt;/span&gt;
    &lt;/button&gt;
  &lt;/li&gt;
&lt;/ul&gt;  
</code></pre>

<p>How you would style the active state is quite up to you, but I&#8217;d personally save on writing class attributes to the <code>&lt;span&gt;</code>s with JavaScript. Instead, I&#8217;d write some CSS using pseudo classes to target the relevant span dependent on the state.</p>

<pre><code>[role="switch"][aria-checked="true"] :first-child, 
[role="switch"][aria-checked="false"] :last-child {
  background: #000;
  color: #fff;
}
</code></pre>

<h4 id="traversingthesettings">Traversing the settings</h4>

<p>Now let&#8217;s talk about navigating through this settings section using two different strategies: by <kbd>Tab</kbd> key (jumping between focusable elements only) and browsing by screen reader (moving through each element).</p>

<p>Even when navigating by <kbd>Tab</kbd> key, it&#8217;s not only the  
identity and state of the interactive elements you are focusing that  
will be announced in screen readers. For example, when you focus the  
first <code>&lt;button&gt;</code>, you&#8217;ll hear that it is a <em>switch</em> with the label &#8220;Notify by email&#8221;, in its <em>on</em> state. &#8220;Switch&#8221; is the role and <code>aria-checked="true"</code> is vocalized as &#8220;on&#8221; where this role is present.</p>

<aside>  
<h4>Switch role support</h4>  
<p>The <code>switch</code> role is not quite as well supported as <code>aria-pressed</code>. For example, it is not recognized by the ChromeVox screen reader extension for Chrome.</p>  
<p>However, ChromeVox <em>does</em> support <code>aria-checked</code>. This means that, instead of <em>&#8220;Switch, Notify by email, on&#8221;</em> being announced, <em>&#8220;Button, Notify by email, checked&#8221;</em> is instead. This isn&#8217;t as evocative, but it is adequate. More than likely, it will simply be mistaken for a checkbox input.</p>  
<p>Curiously, NVDA regards a button with <code>role="switch"</code> and <code>aria-checked="true"</code>  
 as a toggle button in its pressed state. Since on/off and 
pressed/unpressed are equivalent, this is acceptable (though slightly  
disappointing).</p>  
</aside>

<p>But in most screen readers you&#8217;ll also be told you&#8217;ve entered a list  
of four items and that you&#8217;re on the first item — useful contextual  
information that works a bit like the group labelling I covered earlier  
in this post.</p>

<p>Importantly, because we have used <code>aria-labelledby</code> to associate the adjacent text to the button as its label, that is also available when navigating in this mode.</p>

<p>When browsing from item to item (for example, by pressing the down  
key when the NVDA screen reader is running), everything you encounter is  
 announced, including the heading (<em>&#8220;Notifications, heading level two&#8221;</em>). Of course, browsing in this fashion, <em>&#8220;Notify by email&#8221;</em>
 is announced on its own as well as in association with the adjacent 
button. This is somewhat repetitive, but makes sense: &#8220;Here&#8217;s the  
setting name, and here&#8217;s the on/off switch for the setting of this  
name.&#8221;</p>

<p>How explicitly you need to associate controls to the things they  
control is a finer point of UX design and worth considering. In this  
case we&#8217;ve preserved our classic on/off switches for sighted users,  
without confusing or misleading either blind or sighted screen reader  
users no matter which keyboard interaction mode they are using. It&#8217;s  
pretty robust.</p>

<h2 id="conclusion">Conclusion</h2>

<p>How you design and implement your toggle buttons is quite up to you,  
but I hope you&#8217;ll remember this post when it comes to adding this  
particular component to your pattern library. There&#8217;s no reason why  
toggle buttons — or any interface component for that matter — should  
marginalize the number of people they often do. </p>

<p>You can take the basics explored here and add all sorts of design  
nuances, including animation. It&#8217;s just important to lay a solid  
foundation first.</p>

<h3 id="checklist">Checklist</h3>

<ul>  
<li>Use form elements such as checkboxes for on/off toggles if you are certain the user won&#8217;t believe they are for  submitting data.</li>  
<li>Use <code>&lt;button&gt;</code> elements, not links, with <code>aria-pressed</code> or <code>aria-checked</code>.</li>  
<li>Don&#8217;t change label and state together.</li>  
<li>When using visual &#8220;on&#8221; and &#8220;off&#8221; text labels (or similar) you can override these with a unique label via <code>aria-labelledby</code>.</li>  
<li>Be careful to make sure the contrast level between the button&#8217;s text and background color meets WCAG 2.0 requirements.</li>  
</ul>]]></content:encoded></item></channel></rss>