<p>When I’m done staring with fear-induced catalepsy at the vast array of complex and overlapping app building, testing, integration and deployment tools that are quickly amassing around me, I like to take a little break and try to solve a simple problem. The “current page” link is just such a problem.</p> <h2>The current page</h2> <p>By “current page”, I mean the page you are on right now. It’s <em>this</em> page to you, or to me if I have the vanity to read this post after writing it. In our navigation schema we like to highlight the current page, indicating to the user where they are. A highlighted current page link is like a <strong>YOU ARE HERE</strong> indicator in a shopping mall floor map. I’m rarely <em>there</em>, incidentally, because I hate shopping.</p> <p>The problem with “current page” links is there’s no interoperable (read: accessible) way of communicating them. Unlike links to page fragments, which are identified as “same page link” (or similar) by popular screen readers, the mechanism by which a link points to the current location is not exposed via browsers to assistive technologies. At least, not in my experience.</p> <h2>Class confusion</h2> <p>It’s perfectly simple to add a class — either manually or dynamically — to whichever link corresponds to the current page to add our highlight. Drupal adds an <code>active</code> class to current page links. It’s a poor name because it shares terminology with the <code>:active</code> state, but it does the job.</p> <pre><code><nav role="navigation"> <ul> <li><a href="/" class="active">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav></code></pre> <p>Unfortunately, this class, as all classes, will remain uninterpreted by screen readers. Screen readers do not read classes. Classes do not climb <a href="http://www.w3.org/WAI/PF/aria-implementation/#intro_treetypes">accessibility trees</a>. In order to provide an aural indication of context, we’ll need to try something else.</p> <h2>Accessible names</h2> <p>The <a href="http://www.w3.org/TR/wai-aria-1.1/roles#namecalculation">accessible name</a> of an element — its lexical content — is calculated by one of</p> <ul> <li>the element’s text node,</li> <li>the value of any associated <code>aria-label</code> or <code>aria-labelledby</code> attributes,</li> <li>the <code>alt</code> attribute if it’s an image etc.,</li> <li>the <code>title</code> attribute. Don’t leave it up to the <code>title</code> attribute. That’s flimsy as hell.</li> </ul> <p>Unavoidably, if we want to do the right thing here and communicate the current page both visually <em>and</em> aurally, using an accessible name is the key. First let’s try adding some text.</p> <h2>The span approach</h2> <pre><code><nav role="navigation"> <ul> <li><a href="/" class="active">Home <span class=”visually-hidden”>current page</span></a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav></code></pre> <p>This is pretty good, but necessitates the hacky “hide to visual users but not to screen reader users” approach of clipping the <code><span></code> text or hiding it off screen. Because the span communicates nothing visually, we are then forced to tackle the same problem separately for visual users: We have to leave the <code>.current</code> class intact.</p> <h2>The aria-label approach</h2> <p>The <code>aria-label</code> attribute can be added to elements which are lacking a text node. Commonly, <code><button></code>s with just unicode icons or background images.</p> <pre><code> <nav role="navigation"> <ul> <li><a href="/" class="active" aria-label="current page">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav></code></pre> <p>I prefer this to the “shove a span in there” approach for one reason above all: You can use the <code>aria-label</code> attribute in a selector. By pairing the accessible name with the style you can <strong>remove the class</strong>, tidying up the <strong>HTML</strong>. More important than tidiness, though, is the creation of a mechanism whereby the visual appearance of “current page” and the aural announcement of “current page” are paired. That is, when you move the <code>aria-label</code> between links, you are doing it for both kinds of user.</p> <pre><code>[aria-label="current page"] { /* highlighted styles */ }</code></pre> <p>Roger Johansson notes <a href="https://twitter.com/rogerjohansson/status/434215633333399552">an internationalization problem</a> with this method. Should we translate the site to French, we would want to change the “current page” value of the <code>aria-label</code> to “page actuelle” or similar. This would break the above selector. You could change the selector to <code>[aria-label]</code> so it just matches the <em>presence</em> of the attribute — which would only be on our current link — but there’s a bigger problem with <code>aria-label</code> than that.</p> <h3>The problem</h3> <p>Having been testing in VoiceOver, I was fully expecting the “current page” text to be appended (or is it prepended? It doesn’t matter) to the text node — “current page home”, for example. Unfortunately, for our purposes, <strong>NVDA</strong>, <strong>JAWS</strong> and ChromeVox all <em>override</em> the text node with the label, leaving just “current page”. Irritatingly cryptic to most users, I would imagine...</p> <ul> <li>Home</li> <li>About</li> <li>Contact</li> <li>Current page</li> <li>Blog</li> </ul> <h2>The aria-describedby approach</h2> <p>Unlike <code>aria-label</code>, <code>aria-describedby</code> is actually specified to append its value to the target element’s text node. I have set up a <a href="http://codepen.io/heydon/pen/BdpEn">test case on CodePen</a> where you will note that both <strong>JAWS</strong> and <strong>NVDA</strong> both read “home link current page” when focusing the “home” navigation item. The markup looks like this:</p> <pre><code><nav role="navigation"> <ul> <li><a href="/" aria-describedby="current">home</a></li> <li><a href="/about">about</a></li> <li><a href="/contact">contact</a></li> </ul> <div id="current">current page</div> </nav></code></pre> <p>Naturally, we hide <code>#current</code> with <code>display: none</code>. This will make it invisible to all users. Now, only one item needs translating and it’s easier because it is text which appears within the document rather than an attribute value. The <code>aria-describedby</code> value need not change as it just forms a relationship with <code>#current</code>. This is the best solution I have come up with.</p> <h2>aria-current</h2> <p>You may or may not know that <strong>WAI-ARIA</strong> tab interfaces have an <code>aria-selected</code> attribute which can be used to indicate the “open” tab in such an interface. “Selected tab” (or “tab selected”) is communicated whenever the selected tab is focused.</p> <pre><a role="tab" aria-selected="true">My tab</a></pre> <p>Note how I have omitted the class. As in our “current page” example there’s no need for it, because the presence of the <code>aria-selected</code> attribute can do all the work. The <a href="http://www.w3.org/WAI/PF/aria-practices/20091214/#docmgt"><strong>W3C</strong> recommend</a> tying state to appearance in this way, in fact:</p> <blockquote> <p>For supporting browsers, tie CSS attribute selectors to WAI-ARIA properties to reduce script</p> </blockquote> <p>Like <code>aria-checked</code> and <code>aria-pressed</code>, <code>aria-selected</code> is intended to communicate the selected state of a control amongst other controls. It’s tempting to think <code>aria-selected</code> would be suitable for the use case I am exploring for “current” pages, but there are conceptual differences between that which is “on” or “chosen” and one’s location within a continuum. Accordingly, <a href="http://lists.w3.org/Archives/Public/public-pfwg/2013Oct/0059.html">Léonie Watson has been discussing</a> <code>aria-current</code> as a proposed standard method for indicating one’s current location within a site or step-based process. What do you think?</p> <h2>Remove the link?</h2> <p>One more approach, as suggested to me by <a href="https://twitter.com/schofeld/status/434233011237036034">Jonathan Schofield</a>, would be to remove the link for the current page altogether.</p> <pre><code><nav role="navigation"> <ul> <li><strong>home</strong></li> <li><a href="/about">about</a></li> <li><a href="/contact">contact</a></li> </ul> </nav></code></pre> <p>Though perhaps a bit more of a handful styling wise, this makes sense to me. Why link to the place you’ve arrived at already? My only concern is that a <code><strong></code>, <code><span></code> or other inert element would be unfocusable, not allowing a screen reader user the context we are trying to communicate.</p> <h2>This is design</h2> <p>The next time someone asks me what web design is or categorizes me as a “visual designer”, I’m going to send them to this post. You are welcome to as well. Any other suggestions for “current page” solutions, anyone?</p>
The Accessible Current Page Link Conundrum
Read the full piece at https://heydonworks.com/article/the-accessible-current-page-link-conundrum/