11.3 Providing accNames to icon buttons

Ein Icon-Button ist ein Button der ein Icon als Label und keinen sichtbaren Begleittext hat.

5 Methoden und ihre Vor- und Nachteile

Wir verwenden also ein <button>-Element, da dieses die nötige Semantik mitbringt und Screenreader sofort wissen, was Sache ist. Ein Bild bzw. ein Icon wäre ungeeignet.
Als Icon hat sich SVG bewährt, da das die semantisch beste, flexibelste und resilienteste Methode ist, um Icons auf einer Website zu implementieren. Grafiken wie Icons zu repräsentieren ist wörtlich das, wozu SVG gemacht wurde. Wird ein SVG als Icon verwendet, kann man dem SVG selbst einen accName geben, das der Browser verwenden kann, um einen accName für den Button zu berechnen.


Eine andere gebräuchliche Methode ist ein Icon-Font + CSS. Icon-Fonts sind aufgrund diverser Einschränkungen viel weniger flexibel und riskant. Wenn der Font nicht geladen oder das CSS nicht verwendet wird, kann das Icon nicht angezeigt werden.

<button><i class="fa fa-bars"></i></button>

1. Button-Text mit .visually-hidden verstecken

Zunächst hat der Button noch keinen Namen. Der User weiß daher nicht, welchen Zweck der Button hat bzw. welche Aktion damit initiiert wird. Das ist eine Verletzung von SC 4.1.2 Name, Role, Value (Level A)
Die optimale Möglichkeit, dem Button einen accName zu geben, wäre HTML-Content (also der Text innerhalb des <button>-Elements). Allerdings wollen wir ja hier gerade keinen Text haben.

Anm.: In diesem Fall ist die Icon-Grafik doppelt gemoppelt, daher wird diese mit aria-hidden="true" vor dem Screenreader versteckt. Aber hier geht es ja eigentlich um etwas anderes!

<button class="icon-button">
  <svg height="21" viewBox="0 0 21 21" width="21" aria-hidden="true">
    ...
  </svg>
  Like
</button>

Der einfachste und stabilste Weg, das Label zu verstecken, geht mit der Klasse .visually-hiden. So bleibt es für Screenreader zugänglich.
Das SVG wird, wie im Beispiel oben, mit aria-hidden="true" vor dem Screenreader versteckt!

<button class="icon-button">
  <svg height="21" viewBox="0 0 21 21" width="21" aria-hidden="true">
    ...
  </svg>
  <span class="visually-hidden">Like</span>
</button>

2. hidden + aria-labelledby ★ Go-To method ★

Der Label-Text wird mit hidden versteckt, aber mittels aria-labelledby als accName für den Button definiert. Die Vorteile von hidden ggü. .visually-hidden wurden bereits erwähnt (wenn CSS nicht geladen werden kann, keine Pause bei Reader Mode, ...)

<button class="icon-button" aria-labelledby="edit-btn-label">
    <svg height="21" viewBox="0 0 21 21" width="21" aria-hidden="true">
      ...
    </svg>
  <span id="edit-btn-label hidden">Edit</span>
</button>

3. aria-label für den Button

aria-label überschreibt den Textinhalt des Buttons. Weder dieser Text noch das Icon werden benutzt, um einen accName zu generieren. Falls der Button ein Text-Label hat, wird dieses auch nicht als Teil des accNames des Button angezeigt. Damit würde wieder ein Problem für Spracheingabe entstehen (Mismatch zwischen accName und angezeigtem Text). Verletzung von SC 2.5.3 Label in name. Wenn aria-label verwendet wird, sollte der Button keinen Text haben, und falls doch, muss der Button-Text identisch mit dem aria-label sein!

<button class="icon-button" aria-label="Download">
    <svg height="21" viewBox="0 0 21 21" width="21" aria-hidden="true">
      ...
    </svg>
  dummy-text
</button>

4.+5. svg-Icon selbst stellt einen accName zur Verfügung

SVG ist Teil des Inhalts des Buttons! Der accName des svg sollte beschreiben, was der Button macht, nicht das Icon selbst.

  1. Das <svg> nicht mit aria-hidden verstecken.
  2. Das <svg> als Image auszeichnen role="img", und
  3. ihm einen Namen geben, der den Zweck des Buttons beschreibt:
    • entweder mit einem <title>-Element* (Send) Zur Zeit problematisch mit VoiceOver! Workaround: explizite Verbindung mit aria-labelledby, funktioniert aber leider nicht mit Firefox.
    • oder mit einem aria-label-Attribut für das <svg>-Element (Delete) Zur Zeit die robusteste Methode, wenn das SVG benannt wird.

* Das <title>-Element ist für ein SVG das, was ein alt-Attribut für ein <img> ist. Das <title>-Element muss das erste Kindelement des <svg> sein!

Zur Zeit sind die Resultate bei den verschiedenen Browser- und Screenreader-Kombinationen nicht konsistent!

<button class="icon-button" >
  <svg height="21" viewBox="0 0 21 21" width="21" role="img" aria-labelledby="send-btn-label">
      <title id="send-btn-label">Send</title>
      ...
  </svg>
</button>
<button class="icon-button">
  <svg height="21" viewBox="0 0 21 21" width="21" role="image" aria-label="Delete">
    ...
  </svg>
</button>

Relevante Success Criteria

SC 4.1.2 Name, Role, Value (Level A)
For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.

Wichtigstes Takeaway von diesem Kapitel:

Teste immer, immer selbst, um sicherzustellen, dass ein Pattern funktioniert (oder eben nicht). Dinge ändern sich.

Links