Komponenten · Medien & Daten

Icons & SVGs barrierefrei einbinden

Ein Icon braucht nur dann einen zugänglichen Namen, wenn es Information trägt, die sonst nirgends steht – alles andere wird mit aria-hidden="true" versteckt. Sitzt das Icon allein in einem Button oder Link, gehört der Name an das Bedienelement, nicht an das Symbol.

Icons sind klein, aber barrierefrei überraschend tückisch, weil dasselbe Symbol zwei völlig verschiedene Rollen spielen kann: mal reine Begleitung neben einem Text, mal der einzige Inhalt eines Bedienelements. Wie verbreitet der zweite Fall schiefgeht, zeigt der WebAIM-Million-Report vom Februar 2026: Auf 46,3 % aller untersuchten Startseiten gab es Links ohne erkennbaren Text – und der namenlose Icon-Link ist dabei der Klassiker.

Das Wichtigste in Kürze

  • Die Leitfrage lautet: Geht ohne das Icon Information verloren? Nein heißt verstecken, ja heißt beschriften.
  • Dekoratives Inline-SVG bekommt aria-hidden="true" und zusätzlich focusable="false".
  • Beim Icon-Button trägt der Button den Namen, per aria-label oder – besser – per sichtbar verstecktem Text.
  • Ein Icon, das für sich steht, braucht role="img" plus aria-label. Ohne die Rolle ignorieren manche Screenreader das Label.
  • Steht ein sichtbares Wort am Bedienelement, muss es im zugänglichen Namen vorkommen – sonst greift WCAG 2.5.3 nicht und die Sprachsteuerung findet den Knopf nicht.
  • Bedeutungstragende Icons brauchen 3:1 Kontrast (WCAG 1.4.11) und eine Zielfläche von mindestens 24 × 24 CSS-Pixeln (WCAG 2.5.8).
  • Icon-Fonts sind der unsicherste Weg: Screenreader lesen im Zweifel das zugrunde liegende Zeichen, und bei blockierter Schrift bleibt ein leeres Kästchen.

Deko oder Bedeutung: die eine Frage

Vor jeder technischen Entscheidung steht dieselbe inhaltliche: Trägt das Icon Information, die im Text nicht schon steht? Daraus ergeben sich genau drei Fälle:

Drei Karten nebeneinander. Erstens: Download-Icon neben dem Text „Download (PDF, 2 MB)“, ausgezeichnet mit aria-hidden=true und focusable=false, Ansage „Link, Download PDF 2 MB“. Zweitens: Lupensymbol allein in einem blauen Knopf, der Knopf trägt aria-label=Suche öffnen, das SVG ist aria-hidden, Ansage „Suche öffnen, Schaltfläche“. Drittens: grünes Häkchen neben „Bestellung 4711“, das SVG trägt role=img und aria-label=Bezahlt, Ansage „Grafik Bezahlt, Bestellung 4711“.
Dasselbe Prinzip in drei Ausprägungen: verstecken, den Namen ans Bedienelement hängen oder das Symbol selbst beschriften.

Dekoratives Icon verstecken

Steht neben dem Icon ohnehin ein Text mit derselben Aussage, ist das Icon Deko. Es wird vor assistiver Technik versteckt, damit es nicht doppelt angesagt wird:

<a href="/download.pdf">
  <svg aria-hidden="true" focusable="false" width="20" height="20">…</svg>
  Download (PDF, 2 MB)
</a>

aria-hidden="true" nimmt das SVG aus dem Accessibility-Baum. Das focusable="false" stammt aus der Zeit von Internet Explorer und altem Edge, in der Inline-SVGs einen eigenen Tabstopp erzeugten. Aktuelle Browser tun das nicht mehr – das Attribut kostet aber nichts und schützt vor Altlasten, deshalb sitzt es bei mir weiter im Standard-Snippet.

Bindest du das Icon stattdessen als Bilddatei ein, gelten die normalen Bildregeln: ein leeres alt="" für Deko, ein beschreibendes alt für Bedeutung. Das ist dann kein SVG-Spezialfall mehr, sondern Alt-Text-Handwerk.

Der Icon-Button

Der häufigste Fehler überhaupt: ein Button, der nur ein Symbol enthält – eine Lupe, ein Hamburger, ein „ד. Für das Auge ist klar, was gemeint ist. Ein Screenreader sagt „Schaltfläche“ und sonst nichts.

Zwei Werkzeugleisten im Vergleich. Links fünf reine Icon-Knöpfe, die Screenreader-Ausgabe lautet fünfmal „Schaltfläche“ – einer der Knöpfe löscht, welcher ist nicht erkennbar. Rechts dieselben Knöpfe mit sichtbaren Beschriftungen Liste, Export, Löschen, Freigeben und Einstellungen, die Ansagen lauten „Ansicht als Liste, Schaltfläche“, „Export starten, Schaltfläche“, „Auswahl löschen, Schaltfläche“ und so weiter. Darunter ein Hinweis zur Sprachsteuerung und WCAG 2.5.3.
Fünf namenlose Knöpfe klingen alle gleich – auch der, der löscht.

Die Lösung: Der Button bekommt den Namen, das Icon wird versteckt.

<button type="button" aria-label="Suche öffnen">
  <svg aria-hidden="true" focusable="false" width="24" height="24">…</svg>
</button>

Ich pack den Namen konsequent ans Bedienelement, nie ans Symbol. Auch wenn beides technisch möglich wäre: Der Button ist das, was fokussiert und aktiviert wird, also gehört der Name dorthin.

aria-label oder versteckter Text?

Beide Varianten erzeugen denselben zugänglichen Namen, haben aber unterschiedliche Nebenwirkungen:

<!-- Variante A: aria-label -->
<button type="button" aria-label="Suche öffnen">
  <svg aria-hidden="true" focusable="false">…</svg>
</button>

<!-- Variante B: sichtbar versteckter Text -->
<button type="button">
  <svg aria-hidden="true" focusable="false">…</svg>
  <span class="visually-hidden">Suche öffnen</span>
</button>

Variante B hat drei Vorteile: Der Text wird von Übersetzungsdiensten mitübersetzt (ein aria-label oft nicht), er lässt sich per Suchfunktion finden, und er verschwindet nicht, wenn ein Nutzerskript ARIA-Attribute ignoriert. Dieselbe Abwägung gilt auch bei Labels und Beschriftungen.

Und noch besser als beides: das Wort einfach hinschreiben. Ein Icon mit sichtbarer Beschriftung darunter ist für alle verständlicher – für ältere Nutzerinnen, für Menschen mit kognitiven Einschränkungen und für jeden, der die Metapher nicht kennt.

Wichtig ist dann nur eines: Steht sichtbar „Löschen“ am Knopf und im Code aria-label="Entfernen", findet die Sprachsteuerung den Knopf nicht mehr. Der sichtbare Text muss im zugänglichen Namen vorkommen – das verlangt 2.5.3 Beschriftung im Namen.

Bedeutungstragendes Icon beschriften

Steht ein Icon für sich – ohne begleitenden Text und ohne Bedienelement drumherum –, braucht das Symbol selbst einen Namen:

<svg role="img" aria-label="Bezahlt" focusable="false" width="20" height="20">

</svg>

Die Rolle ist dabei nicht optional: Ohne role="img" ignorieren mehrere Screenreader das aria-label am <svg>-Element schlicht. Alternativ kann ein <title> als erstes Kind dienen, per aria-labelledby verknüpft:

<svg role="img" aria-labelledby="titel-bezahlt" focusable="false">
  <title id="titel-bezahlt">Bezahlt</title>

</svg>

In der Praxis bleibe ich bei role="img" plus aria-label, weil es weniger Fallstricke hat: Der <title> muss wirklich das erste Kind sein, die ID muss eindeutig bleiben, und bei kopierten Sprites steht sie schnell doppelt im Dokument.

Fünf Einbindungsarten im Vergleich

Art Barrierefreiheit Praktische Grenzen
Inline-SVG volle Kontrolle über Rolle und Namen bläht das HTML auf, kein Browser-Cache
<img src="icon.svg"> normale alt-Regeln, sehr robust kein currentColor, keine CSS-Steuerung von innen
<use> mit Sprite wie Inline-SVG, aber wiederverwendbar externe Datei muss laden, <title> im <symbol> greift unzuverlässig
CSS background-image für assistive Technik unsichtbar nur für reine Deko; verschwindet oft im Kontrastmodus
Icon-Font Zeichen wird im Zweifel vorgelesen versagt bei blockierter Schrift und eigenen Stylesheets

Zwei Anmerkungen dazu, die in der Tabelle zu kurz kommen:

Sprites mit <use>. Rolle und Name gehören an das äußere <svg>, nicht in das <symbol>. Ein <title> innerhalb des Symbols wird beim Einbinden über <use> je nach Browser gar nicht in den Accessibility-Baum übernommen – verlässlich ist nur, was am einbindenden Element steht.

<svg role="img" aria-label="Warenkorb" focusable="false">
  <use href="/icons/sprite.svg#warenkorb"></use>
</svg>

Icons im Kontrastmodus. Symbole, die als background-image liegen, verschwinden im Windows-Kontrastmodus regelmäßig oder werden unlesbar. Wer sie per mask-image mit background-color: currentColor umsetzt, bekommt Icons, die die erzwungene Farbe mitmachen. Für rein dekorative Symbole ist das verschmerzbar – für alles andere nicht.

Ein Nebenaspekt, der die Wahl mitentscheidet: Inline-SVG kostet keinen zusätzlichen Request und blockiert nichts, ein Icon-Font dagegen ist eine weitere Schriftdatei im kritischen Pfad. Auf Seiten, deren größtes sichtbares Element ohnehin knapp am LCP-Budget liegt, ist das ein messbarer Unterschied – siehe LCP & INP gezielt optimieren.

Icon-Fonts: dasselbe Prinzip, mehr Risiko

Bei Icon-Fonts entsteht das Symbol aus einem Schriftzeichen, meist aus dem Bereich für private Nutzung. Screenreader lesen im Zweifel das zugrunde liegende Zeichen vor – oder den Namen der Ligatur, also etwa „delete“ mitten im Satz.

<span class="icon icon-warenkorb" aria-hidden="true"></span>
<span class="visually-hidden">Warenkorb öffnen</span>

Das Prinzip bleibt: Symbol verstecken, Sinn über echten Text liefern. Der zweite Grund gegen Icon-Fonts hat mit Screenreadern nichts zu tun: Wer eigene Schriften erzwingt – etwa wegen Legasthenie – oder in einer Umgebung mit blockierten Webfonts sitzt, sieht statt des Icons ein leeres Kästchen oder einen zufälligen Buchstaben. Ich greife deshalb seit Jahren zu Inline-SVG.

Sichtbar und verständlich genug

Barrierefreiheit endet bei Icons nicht bei der Auszeichnung. Zwei Erfolgskriterien betreffen die Gestaltung direkt:

  • 1.4.11 Nicht-Text-Kontrast (Stufe AA): Bedeutungstragende Grafiken und Bedienelemente brauchen mindestens 3:1 Kontrast zum Hintergrund. Das hellgraue Icon auf Weiß fällt regelmäßig durch.
  • 2.5.8 Zielgröße (Minimum) (Stufe AA, seit WCAG 2.2): Die Zielfläche misst mindestens 24 × 24 CSS-Pixel. Das Symbol selbst darf kleiner sein, solange die klickbare Fläche drumherum ausreicht – auf Touch-Geräten sind 44 Pixel die bessere Zielmarke.

Und dann ist da noch die Frage, die keine Norm beantwortet: Versteht überhaupt jemand das Symbol? Ein Diskettensymbol für „Speichern“ kennt eine ganze Generation nicht mehr, das Teilen-Icon sieht auf jeder Plattform anders aus, und drei Striche waren jahrelang Gegenstand ernsthafter Forschung. Ein Wort daneben löst das Problem in einer Zeile – und hilft nebenbei allen, die kognitiv entlastet arbeiten.

So testest du Icons

  1. Mit der Tabulatortaste durch die Leiste. Jeder Knopf muss einen eigenen, unterscheidbaren Namen ansagen – „Schaltfläche“ allein ist ein Befund.
  2. Den Accessibility-Baum ansehen. In den Entwicklerwerkzeugen prüfen, ob der berechnete Name am Button steht und das Icon gar nicht auftaucht.
  3. CSS abschalten. Dann zeigt sich, was ohne Gestaltung übrig bleibt – ein guter Test für Icon-Fonts und Hintergrundbilder.
  4. Zoom auf 400 %. Bleiben Symbol und Zielfläche erkennbar und bedienbar?
  5. Sprachsteuerung ausprobieren. „Klick Löschen“ muss den Knopf treffen, an dem sichtbar „Löschen“ steht. Wie das im Alltag aussieht, steht bei Sprachsteuerung.

Häufige Fehler

  • Icon-Button ohne Namen. „Schaltfläche“ ohne jeden Hinweis, was sie tut.
  • Dekoratives Icon nicht versteckt. Wird zusätzlich zum Text angesagt.
  • Name am Icon statt am Button. Der zugängliche Name gehört ans Bedienelement.
  • aria-label ohne role="img" am SVG. Wird von mehreren Screenreadern ignoriert.
  • aria-label widerspricht dem sichtbaren Text. Sabotiert die Sprachsteuerung.
  • <title> im <symbol> eines Sprites. Kommt beim Einbinden über <use> nicht zuverlässig an.
  • Icon zu blass. Unter 3:1 Kontrast ist ein bedeutungstragendes Symbol nicht konform.
  • Zielfläche zu klein. 16 × 16 Pixel sind für die Maus knapp und für zittrige Hände unbrauchbar.

Häufige Fragen

aria-hidden oder leeres alt – wann was?

alt="" gilt für <img>-Elemente, aria-hidden="true" für Inline-SVGs und andere Inline-Elemente. Beide erreichen dasselbe Ziel – „bitte überspringen“ –, nur für unterschiedliche Einbindungsarten. Ein aria-hidden="true" an einem <img> wäre zwar nicht falsch, aber alt="" ist der vorgesehene Weg.

Reicht ein title im SVG nicht aus?

Es kann funktionieren, ist aber empfindlicher: Der <title> muss das erste Kind sein, sauber per aria-labelledby verbunden werden und eine eindeutige ID tragen. Bei Sprites und kopierten Komponenten geht genau das schnell schief. role="img" mit aria-label ist robuster.

Muss ich wirklich jedes dekorative Icon einzeln verstecken?

Ja – aber praktisch ist das eine einzige Stelle. Wenn die Icons aus einer Komponente oder einem Sprite kommen, setzt du aria-hidden="true" und focusable="false" einmal im Template und hast das Thema für alle Vorkommen erledigt.

Was ist mit Emoji statt Icon?

Emoji sind Text und werden mit ihrem offiziellen Namen vorgelesen – „zusammengelegte Hände“ mitten im Satz überrascht. Als schmückendes Beiwerk in einer Überschrift möglich, als Bedienelement oder alleiniger Bedeutungsträger nicht. In einem Button gehört stattdessen ein echtes Wort.

Ja, genau das misst der WebAIM-Report: Ein Link ohne erkennbaren Text – etwa ein Social-Media-Symbol ohne Beschriftung – erzeugt eine Ansage wie „Link“ oder liest die URL vor. Der zugängliche Name gehört ans <a>-Element, nicht ans Symbol.

Fazit

Ob ein Icon Deko oder Bedeutungsträger ist, entscheidet alles: Deko wird mit aria-hidden="true" und focusable="false" versteckt, ein Icon-Button bekommt den Namen am Button, ein freistehendes Symbol role="img" plus aria-label. Mit diesen drei Mustern sind die allermeisten Fälle abgedeckt.

Der Rest ist Gestaltung: 3:1 Kontrast, 24 × 24 Pixel Zielfläche und im Zweifel ein sichtbares Wort neben dem Symbol. Das ist die Lösung, die am wenigsten Technik braucht und am meisten hilft – ganz im Sinne der ersten Regel von ARIA, nach der das einfachste Mittel zuerst kommt.

Quellen

  • Functional Images (W3C WAI – Textalternativen für Icons in Links und Buttons, inklusive Sonderfall Icon plus Text)
  • The WebAIM Million 2026 (WebAIM – 46,3 % der Startseiten mit Links ohne erkennbaren Text)
Gratis E-Book PDF Das Praxishandbuch

Kostenloses E-Book

Das Praxishandbuch für sauberes, zugängliches Web

Alles rund um semantisches HTML, Barrierefreiheit, WCAG & BFSG, GEO und SEO — praxisnah und am echten Code. In mehreren Feedbackschleifen von Leserinnen und Lesern verbessert.

  • 3.000+ Downloads
  • 7. Auflage
  • 37 Seiten
  • PDF

Kein Spam. Abmeldung jederzeit mit einem Klick möglich.