WAI Aria Rollen und Eigenschaften bieten zusätzliche Semantik in Attribut-Form. Ihr erklärtes Ziel ist die Verbesserung der Zugänglichkeit von Webseiten – insbesondere für Blinde, aber auch für Tastaturnutzer sowie andere Behinderungen. Daneben sind theoretisch auch die – für eine Verbesserung der Semantik – üblichen positiven Nebeneffekte für Suchmaschinen, Browser-Features und Gebrauchstauglichkeit denkbar.
ARIA bietet zusätzliche Semantik für
- Rollen von typischen JS-Widgets (z.B. tree, menubar)
- jeweilige Zustände/Eigenschaften (z.B.: aria-hidden bzw. aria-haspopup, aria-required)
- Rollen für strukturelle Elemente und Beziehungen zwischen ihnen (z.B. seealso, navigation etc.)
- Rollen für logische Bereiche (z.B. allgemein: section, region, bei Ajax: liveregion, konkrete: main)
Aufgrund ihrer bereits breiten Unterstützung, der Lösung der wohl drängendsten Zugänglichkeitsprobleme sowie der Tatsache, dass Aria noch nicht validieren, scheinen derzeit die Rollen und Eigenschaften zur Beschreibung von Widgets am interessantesten.
Das Rollen-Konzept von WAI Aria
Das Rollen Konzept ist für Web Entwickler grundsätzlich nichts neues. Über semantisches HTML wird über die Zugänglichkeitsschnittstelle letztendlich die Rolle des Elements dem Screenreader mitgeteilt, welcher sich dann der Rolle entsprechend verhalten kann (z.B.: in Form von Information sowie Interaktionsmöglichkeiten).
Die Aria-Widget-Rollen sind an die Rollen der jeweiligen Zugänglichkeitsschnittstellen angelehnt, welche diese bereits nutzen, um Rollen von Interaktionselementen innerhalb des Betriebssystems bzw. einzelner Applikationen zugänglich zu machen. Aufgabe der Browser ist es die Aria-Rollen auf die genaue Rolle der jeweiligen Zugänglichkeitsschnittstelle zu „mappen”. (Beispiele des Aria-Rollen-Mappings für Gecko-Browser je nach vorhandener Schnittstelle).
Einhaltung von Interaktionskonventionen
Aus dem obigen Konzept folgt semantische Gleichheit/Ähnlichkeit zwischen einem Aria-Widget und seinem Pendant innerhalb von „richtigen” Applikationen.
Das nachfolgende Beispiel enthält die selben semantischen Informationen wie die Menüleiste des Firefox-Browser (nicht alle).
Beispiel für eine Menüleiste :
<div role=”menubar”>
<span role=”menuitem” aira-haspopup=”true” tabindex=”0″> Datei</span>
<div role=”menu”>
<span role=”menuitem” tabindex=”-1″> Neues Fenster</span>
<span role=”menuitem” tabindex=”-1″> Neuer Tab</span>
</div>
</div>
Jaws würde dies beim ersten fokussieren ungefähr wie folgt vorlesen: Menüleiste – Menupunkt – Datei – Untermenü – Sie können mit den Pfeiltasten links / rechts navigieren.
Das Tastaturverhalten wird weder von Browser noch vom Screenreader geliefert, sondern ist alleinige Sache des Autors.
Hierbei sollte er sich beim Scripten der Interaktionsmöglichkeiten, am Original-Verhalten des typischen Widgets innerhalb des Betriebssystems orientieren.
Die WAI-ARIA Best Practices sowie das AOL Developer Network enthalten hierzu, zu einigen Widgets entsprechende Empfehlungen für Maus- und Tastatur-Interaktionen.
Die Bedeutung des Focus
Damit der Screenreader die Rolle sowie Eigenschaften des jeweils aktiven Widget-(Unter-)Elements begreifen kann, muss dieses – insbesondere wenn es Interaktionsmöglichkeiten bietet – in der Regel fokusiert werden. Um die Fokusierbarkeit bei allen Elementen zu ermöglichen, wurde das tabindex-Attribut zum Universalattribut deklariert. Bekommt das tabindex-Attribut den Wert „0″, ist es in der normalen Tabreihenfolge durch den User fokussierbar. Hat es dagegen den Wert „-1″, liegt es außerhalb der Tabreihenfolge, kann jedoch vom Autoren mit JavaScript fokussiert werden (Bei Aria-Widgets für „Unterelemente” der Normalfall.). (Näheres zum Setzen/Auslesen des tabindex per JavaScript.)
Fokus setzen
Für das eigentliche Fokussieren durch den Autoren stehen zwei Möglichkeiten bereit:
- Die focus-Methode des jeweiligen Element-Objekts
- Das Attribut activedescendant
Um den Fokus mit der focus-Methode zu setzen, sollte diese mit einem Timeout aufgerufen werden, um Fehlverhalten in den Browsern zu umgehen. Eine Funktion die dies übernimmt, könnte beispielsweise so aussehen:
function setFocus(elem) {
setTimeout(function(){
elem.focus();
}, 1);
}
Bei meinen Tests mit einem Accordion-Widget hat sich gezeigt (hier gibt es keine spezifischen Aria-Rollen), dass ein Timeout von mehr als 180ms notwendig ist, damit Jaws (9.0) beim Vorlesen den neu angezeigten Bereich nicht überspringt.
Bei der activedesendant-Methode bekommt das tatsächlich fokussierte Element das Attribut activedescendant mit der ID des „virtuell” fokussierten Elements.
Stylen des Fokus
Daneben muss das fokussierte Element entsprechend gestylt werden. Damit dies richtig funktioniert, sollte nicht auf die Pseudo-Selectoren :focus/:active zugegriffen, sondern beim Event „focus” eine entsprechende CSS-Klasse gesetzt und beim Event „blur” wieder entfernt werden.
Alles im Blick
Bei vielen Widgets wird der Autor die Tastaturfunktionalität über die Pfeiltasten realisieren und hierbei das default–Verhalten des Browser unterbinden müssen. Daher sollte darauf geachtet werden, dass insbesondere die wichtigen Bereiche des Widgets immer im Viewport bleiben. Grundsätzlich wird dies bereits durch das Fokusieren des aktiven Elements erledigt. In bestimmten Fällen kann man sich hierauf alleine jedoch nicht verlassen.
Gründe hierfür können sein:
- der interessante Bereich ist größer z.B. kleiner Menüpunkt öffnet großes Untermenü
- man fokusiert nicht „physisch” sondern mit Hilfe des activedescendant-Attributs
- Das fokusierte Element spannt sich nicht vollständig auf
In diesen Fällen kann mit der Methode „scrollIntoView”, CSS-Anpassung oder ganz kompliziert durch Abfragen des Viewports, des Scrollbereichs sowie der Position des DOM-Elements der neue scrollLeft/scrollRight-Wert berechnet und das DOM-Element in den Viewport geschoben werden.
fliegender Wechsel zwischen Maus und Tastaturnutzung
Bei vielen Widgets sollte der Autor darauf achten, dass ein Wechsel zwischen Maus und Tastaturnutzung möglich ist. D. h. Hat der User beispielsweise einen Menüpunkt aktiviert und drückt der User auf die Pfeiltaste rechts, muss das Untermenü – sofern vorhanden – geöffnet und der 1. Menüpunkt aktiviert werden. Ähnlich sieht es beispielsweise bei einem Slider-Widget aus. Hat der User es mit der Maus aktiviert und fängt an zu ziehen, sollte mit den Pfeiltasten link/rechts ebenfalls in Kontakt treten können, ohne vorher mit Tab den Fokus selbst setzen zu müssen.
1.0 Semantik überschreiben
Das Role Attrbibut überschreibt die Sematik herkömmlicher HTML-Elemente. Hierbei sollte darauf geachtet werden, dass keine „falsche” Semantik zurückbleibt. Diese kann mit der Rolle „presentation” überschrieben werden.
Beispiel (Menuleiste):
<ul role=”menubar”>
<li role=”presentation”>
<a href=”#” role=”menuitem” aira-haspopup=”true”> Datei</a>
<div role=”menu”>
<ul role=”presentation”>
<li role=”presentation”><a role=”menuitem” tabindex=”-1″> Neues Fenster</a></li>
<li role=”presentation”><a role=”menuitem” tabindex=”-1″> Neuer Tab</a></li>
</ul>
</div>
</li>
</ul>
Grds. sollte es im obigen Beispiel bereits ausreichen das 2. ul Element mit der Presentation-Rolle zu belegen, die dazugehörigen li-Elemente sollten dann ebenfalls nicht als Listenelemente an die Zugänglichkeitsschnittstelle übertragen werden.
Wer ownt, der ownt
Aria schreibt ähnlich wie HTML vor, dass einige Elemente immer Kindelement einer bestimmten Rolle sein müssen. Dies gilt beispielsweise für die Rolle option, welches ein Kind von select oder einer ähnlichen Rolle sein muss. In manchen Fällen ist dies technisch nicht möglich (Ein input-Element kann keine Kinder haben.) oder widerspricht dem Aufbau der UI-Komponente. In diesen Fällen kann das owns-Attribut verwendet werden, welches anzeigt, dass ein Element das Eltern-Element eines anderen ist.
Beispiel (Combobox):
<div role=”combobox” owns=”list”>
<input aria-haspopup=”true” aria-activedescendant=”i2″ type=”text” name=”combox-input” role=”textfield” />
</div>
<!– ganz viel code dazwischen –>
<ul id=”list”>
<li tabindex=”-1″ id=”i1″>Aria</li>
<li tabindex=”-1″ id=”i2″ class=”active”>Aria Best Practices</li>
</ul>
inhaltliche Bedeutung nicht vergessen
Hat man sein Widget mit Aria semantisiert bzw. verwendet eine Bibliothek, welche einem diese Arbeit abnimmt, sollte man ganz besonders darauf achten, ob die inhaltliche Bedeutung des Widgets klar wird. Nutzt man beispielsweise ein Slider-Widget hilft die ganze semantische Auszeichnung nichts, wenn nicht klar wird, was die Eingabe mit Hilfe des Sliders bewirken soll.
Hierfür stehen häufig verschiedene Möglichkeiten zur Verfügung:
- der Text-Knoten des jeweiligen Elements
- das title-Attribut des jeweiligen Elements
- ein mit dem Element verknüpftes label-Element ([for=widget-id])
- Ein Textknoten eines anderen Elements auf das das Widget mit labeldby verweist
Umfangreichere Informationen zum Widget können mit dem Attribut describedby zugänglich gemacht werden.
Fallstricke & Bugs
Grundsätzlich ist Wai-Aria sehr leicht zu implementieren, allerdings gab es bei meinen Versuchen folgende Probleme/offene Fragen:
- Barrierefreiheit 1.0 vs. 2.0
In einigen Fallen weicht das Aria-Konzept von dem ab, was normalerweise beim konventionellen, barrierearmen JavaScript gemacht wird. Dies betrifft insbesondere 2 Punkte.
- Aria implementiert eine verbesserte Tastaturnutzung insbesondere mit Pfeiltasten. Tabben soll in der Regel innerhalb des Widgets nicht verwendet werden können. Vielmehr soll der User hierdruch das Widget verlassen. Screenreader-/Browserkombinationen, die jedoch kein Aria verstehen, könnten einerseits die Nutzung der Pfeiltasten für sich beanspruchen und nicht an den Browser weiterleiten andererseits übernehmen sie häufig Fokusänderungen durch den JavaScript-Autoren nicht.
- Viele Aria-Widgets sollen explizit die display Eigenschaft ‘none’ nutzen, welche mit dem Aria Attribut ‘hidden’ korrespondiert. Währendem nach konventionellem barrierearmen Javascript man in einigen dieser Fälle eher den Inhalt lediglich aus dem Viewport schieben würde.
- Nicht vorhandene, aber evtl. allgemein doch nutzbare Rollen?
Im Web existieren häufig Widgets, welche in Applikationen nicht vorkommen und auch in WAI-ARIA nicht spezifiziert wurden.
Ein Beispiel hierfür wäre beispielsweise ein typisches Accordion. Die Zugänglichkeit eines solchen Widgets kann sicherlich ebenfalls mit Aria erhöht werden, es stellt sich allerdings die Frage welche Rollen und sonstigen Eigenschaften dem Accordion-Widget am nächsten kommen, ohne dass gleichzeitig eine „falsche” Bedienmöglichkeit suggeriert wird. - Bugs im Screenreader
Daneben zeigen sich insbesondere in Jaws noch einige Bugs, die anscheinend darauf zurückzuführen sind, dass die – normalerweise von „richtigen” Programmen benutzen – Rollen noch nicht ausreichend an die Erfordernisse im Web angepasst wurden.
Fazit
Trotz einiger Bugs und anderer Schwierigkeiten ist das Potential von Aria nicht zu unterschätzen. Mich hat schwer beeindruckt, wie sich die Gebrauchstauglichkeit in Screenradern von vielen alltäglichen JavaScript-Widgets mit recht einfachen Mitteln auf hohem Niveau verbessern lässt.
Gute Ressourcen
Wer Lust auf mehr bekommen hat, kann auf eine wachsende Anzahl von Tutorials, Artikeln und Beispielen zurückgreifen:
- Sehr ausführliches Slider Tutorial in 3 Teilen
- Toggle und Tri-State-Button-Tutorial
- Informationen zu aria-required und aria-labeldby/describedby Eigenschaften
- Artikel und Übersicht zu Live Regions
- Einleitung zu Aria mit Übersichten und Beispielen zu den wichtigsten Rollen und Eigenschaften
- Die WAI-ARIA Best Practices
- Viele Aria Beispiele
- Dojo Accessibility Strategy