Klickbare Cards barrierefrei umsetzen

Eine vollständig klickbare Karte baust du mit genau einem echten Link auf der Überschrift, den ein ::after über die gesamte Kartenfläche zieht. Die ganze Karte in ein <a> zu packen ist der falsche Weg. So bleibt der Ankertext kurz und aussagekräftig, verschachtelte Links werden unmöglich, und die Karte ist trotzdem auf voller Fläche anklickbar.

Karten, bei denen die ganze Fläche klickbar ist, sind ein beliebtes Muster und ein häufiger Anlass für kaputtes Markup. Der naive Weg, die gesamte Karte in ein <a> zu packen, schafft mehr Probleme, als er löst. Es geht eleganter, und die Lösung braucht nicht mehr als vier Zeilen CSS.

Das Wichtigste in Kürze

  • Ein Link pro Karte, auf der Überschrift (nicht um die ganze Karte herum).
  • Verschachtelte interaktive Elemente sind ungültig: Ein <a> darf kein zweites <a> und keinen <button> enthalten.
  • Der Ankertext bleibt kurz. In der Linkliste eines Screenreaders steht dann „Bild-SEO“ statt drei Sätzen Fließtext.
  • Das ::after gehört dem Link, nicht der Karte. Nur so bleiben Mittelklick, Rechtsklick und die URL in der Statusleiste erhalten.
  • Der Fokus muss auf der ganzen Karte sichtbar sein, heute elegant mit :has(a:focus-visible).
  • Die Overlay-Fläche schluckt die Textauswahl. Wo das stört, hilft eine kleine JavaScript-Ergänzung (mit einem Nachteil, den man kennen muss).
  • Mehrere Ziele in einer Karte? Dann ist die voll klickbare Fläche der falsche Ansatz.

Warum nicht die ganze Karte in ein <a>?

Eine Karte enthält meist eine Überschrift, Text und vielleicht ein Bild. Packt man alles in einen einzigen Link, entstehen drei Probleme:

Verschachtelte interaktive Elemente. Sobald in der Karte ein zweiter Link, ein Button oder ein Tag-Chip steckt, ist das Markup ungültig. Links dürfen keine Links enthalten. Browser reparieren das eigenwillig, und was am Ende im Accessibility-Tree landet, ist nicht mehr vorhersagbar.

Ein geschwätziger Ankertext. Screenreader lesen den kompletten Linkinhalt am Stück vor. Aus einer Karte wird dann ein Link namens:

„Bild-SEO. Wie Bilder gefunden werden und die Seite stärken. Artikel, 12 Minuten Lesezeit. Grafik: Anatomie eines Bildes. Weiterlesen. Link.“

Besonders schmerzhaft ist das in der Linkliste (der Übersicht, die viele Screenreader-Nutzende aufrufen, um sich einen Überblick zu verschaffen). Aus zwölf knackigen Einträgen werden zwölf Absätze.

Kein markierbarer Text. Was in einem Link steht, lässt sich mit der Maus nicht markieren. Der Zug startet stattdessen einen Link-Drag. Kopieren fällt aus.

Die vier Ansätze im Vergleich

Drei Karten nebeneinander mit je einer Sprechblase für die Screenreader-Ansage. Links die ganze Karte in einem a-Element: die Ansage liest Überschrift, Beschreibung, Lesezeit und Weiterlesen am Stück vor, markiert mit rotem Kreuz. In der Mitte nur die Überschrift verlinkt: kurze Ansage Bild-SEO, Link, aber nur die Überschrift ist klickbar, gelbes Warnzeichen. Rechts das Stretched-Link-Muster: dieselbe kurze Ansage, dazu eine gestrichelte Fläche über der ganzen Karte und ein Fokusrahmen um die Karte, grüner Haken. Vergrößern: Dieselbe Karte, drei Auszeichnungen, drei unterschiedliche Ansagen. Rechts…
Dieselbe Karte, drei Auszeichnungen, drei unterschiedliche Ansagen. Rechts steht das Muster, das diese Seite selbst verwendet.
Ansatz Voll klickbar Ansage Zweitlinks Text markierbar Native Link-Gesten
Ganze Karte im <a> ja geschwätzig unmöglich nein ja
Nur die Überschrift verlinkt nein kurz ja ja ja
Stretched Link (::after) ja kurz mit z-index nein ja
JS-Klick auf der Karte ja kurz mit stopPropagation ja nein

„Native Link-Gesten“ ist die Spalte, die in den meisten Anleitungen fehlt und die den Ausschlag gibt: Mittelklick zum Öffnen in einem neuen Tab, Rechtsklick mit dem Link-Kontextmenü, ⌘- bzw. Strg-Klick, das Ziehen des Links in ein Lesezeichen und die URL, die unten links im Fenster erscheint. All das funktioniert beim Pseudo-Element-Muster, weil die Fläche technisch zum Link gehört. Bei einem JavaScript-Klick-Handler auf der Karte funktioniert nichts davon.

Die saubere Lösung: ein echter Link auf der Überschrift, der per Pseudo-Element die ganze Karte überzieht. Geklickt wird die ganze Fläche, angesagt wird nur der sinnvolle Linktext.

<article class="card">
  <img src="/img/bild-seo.webp" alt="" width="400" height="225" />
  <h3><a href="/seo-und-ki/bild-seo.html">Bild-SEO</a></h3>
  <p>Wie Bilder gefunden werden und die Seite stärken.</p>
  <p class="card-meta">12 Minuten Lesezeit</p>
</article>
.card { position: relative; }

.card h3 a::after {
  content: "";
  position: absolute;
  inset: 0; /* überzieht die ganze Karte */
}

/* Fokus auf der ganzen Karte sichtbar machen */
.card:has(a:focus-visible) {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
.card a:focus-visible { outline: none; }

/* Der Zeiger soll überall zur Hand werden */
.card { cursor: pointer; }

Vier Details entscheiden über Erfolg:

Das position: relative gehört an die Karte, nicht an den Link. Sonst orientiert sich das inset: 0 am nächsten positionierten Vorfahren (im Zweifel am Viewport).

Das ::after gehört dem <a>, nicht der Karte. Genau daran hängen die nativen Link-Gesten aus der Tabelle oben.

Das Bild bekommt alt="", wenn die Überschrift daneben dasselbe sagt. Ein Karten-Bild ist fast immer dekorativ. Mehr dazu unter Alt-Texte schreiben.

Der Fokus wandert nach außen. Ohne den :has()-Block liegt der Fokusrahmen nur um die Überschrift, während die ganze Karte klickbar ist. Das ist ein Missverhältnis, das bei der Tastaturbedienung irritiert. :has() ist seit Ende 2023 in allen aktuellen Browsern verfügbar. Wer ältere Stände bedienen muss, nimmt .card:focus-within als Ersatz. Das gibt es seit 2017 überall und es trifft dieselbe Karte. Ein Unterschied bleibt: :focus-within kennt die Unterscheidung von :focus-visible nicht und zeigt den Rahmen deshalb auch nach einem Mausklick. In einem @supports-Block ist das verschmerzbar, weil es nur dort greift, wo :has() fehlt:

@supports not selector(:has(*)) {
  .card:focus-within {
    outline: 3px solid var(--color-focus);
    outline-offset: 3px;
  }
}

Randnotiz: Genau dieses Muster nutzt diese Seite. Die Themen-Karten auf den Übersichtsseiten und die „Weiterlesen“-Karten am Artikelende sind exakt so gebaut: ein Link auf der Überschrift, ein ::after, das die Karte klickbar macht, plus ein sichtbarer Fokusrahmen über :has(a:focus-visible). Eine Karte, ein Link, klare Ansage.

Der Fallstrick „Weiterlesen“

Sehr verbreitet und selten hinterfragt: Die Karte hat eine verlinkte Überschrift und unten einen „Weiterlesen →“-Link auf dasselbe Ziel. Damit stehen in der Linkliste zwei Einträge für eine Karte. Einer davon heißt „Weiterlesen“ und sagt nichts.

Drei Wege aus der Doppelung:

<!-- 1. Am elegantesten: Weiterlesen ist reine Deko -->
<h3><a href="/seo-und-ki/bild-seo.html">Bild-SEO</a></h3>
<p>…</p>
<span class="card-cta" aria-hidden="true">Weiterlesen →</span>

Der <span> sieht aus wie ein Link, ist aber keiner. Geklickt wird ohnehin die ganze Karte. Alternativ verzichtest du auf den Zusatz, oder du machst umgekehrt nur das „Weiterlesen“ zum Link und gibst ihm per aria-label einen sprechenden Namen. Der letzte Weg ist der schlechteste: Er nimmt der Überschrift den Ankertext, den Suchmaschinen und Screenreader gleichermaßen schätzen.

Text markierbar halten

Das überzogene ::after schluckt die Maus-Auswahl: Wer über den Kartentext zieht, markiert nichts. Bei einer Teaser-Karte ist das verschmerzbar, bei einer Karte mit einem Zitat, einer Adresse oder einer Bestellnummer nicht.

Die Lösung ist ein Tausch (Overlay raus, JavaScript rein):

document.querySelectorAll('.card').forEach((karte) => {
  const hauptlink = karte.querySelector('h3 a');

  karte.addEventListener('click', (event) => {
    // Wer gerade Text markiert hat, will nicht navigieren
    if (window.getSelection().toString()) return;
    // Echte Klicks auf andere Links nicht verdoppeln
    if (event.target.closest('a, button')) return;
    hauptlink.click();
  });
});

Damit ist Text wieder markierbar. Die Karte verliert dabei aber Mittelklick, Rechtsklick-Menü und die URL-Anzeige in der Statusleiste, weil ihre Fläche kein Link mehr ist. Und ohne JavaScript bleibt nur die Überschrift klickbar.

Meine Empfehlung: Standardmäßig das Pseudo-Element, weil es ohne JavaScript funktioniert und alle Link-Gesten erhält. Die JavaScript-Variante nur dort, wo der Kartentext erkennbar zum Kopieren da ist.

Mehrere Aktionen in einer Karte

Sobald eine Karte mehrere Ziele hat (Hauptlink plus „Teilen“, „Merken“, ein Kategorie-Tag), liegt das Overlay über allem und macht die Zweitlinks unerreichbar. Zwei Auswege:

/* Zweitaktionen über das Overlay heben */
.card-secondary {
  position: relative;
  z-index: 1;
}

Das funktioniert technisch, hat aber eine Schwäche: Direkt neben dem „Merken“-Button beginnt die Kartenfläche, und ein knapp danebengegangener Tipp löst die Navigation aus. Für Menschen mit motorischen Einschränkungen ist das eine echte Hürde. Mehr dazu unter motorische Einschränkungen. Wer den Weg geht, sollte um Zweitaktionen herum großzügig Platz freihalten, statt sie einfach nach oben zu stapeln.

Der zweite Ausweg ist ehrlicher: Verzichte auf die voll klickbare Fläche. Dann gibt es echte, getrennt benannte Links und Buttons, und die Karte ist eben nicht komplett klickbar. Klarheit schlägt Komfort.

Die Karte im Screenreader

Drei Fragen zur Semantik, die regelmäßig aufkommen:

<article> oder <li>? Wenn die Karten eine Sammlung gleichartiger Einträge sind, ist eine Liste die bessere Struktur. Screenreader sagen dann „Liste mit 12 Einträgen“ an, was echte Orientierung gibt. <article> innerhalb eines <li> ist zulässig, aber nur dann sinnvoll, wenn der Inhalt für sich stehen könnte. Mehr dazu unter article vs. section und Listen richtig nutzen.

Bild vor oder nach der Überschrift? Solange das Bild alt="" trägt, ist die Frage gleichgültig. Ein leeres alt überspringt der Screenreader. Sobald das Bild etwas beiträgt, das die Überschrift nicht sagt (ein Porträt in einer Teamkarte, ein Produktfoto mit erkennbarem Detail), kehrt sich das um: Steht das <img> im Quelltext vorn, hört man zuerst den Alt-Text und erst danach, worum es überhaupt geht. Dann dreht man die Reihenfolge im Quelltext um und holt das Bild per CSS wieder nach oben:

<article class="card">
  <h3><a href="/team/mira-osei.html">Mira Osei</a></h3>
  <img src="/img/mira-osei.webp" alt="Mira Osei am Whiteboard vor einer Skizze der Fokusreihenfolge" width="400" height="225" />
  <p>Barrierefreiheit und Frontend-Architektur.</p>
</article>
.card { display: flex; flex-direction: column; }
.card img { order: -1; } /* optisch oben, im Quelltext hinter der Überschrift */

Diese Umsortierung ist unbedenklich, weil ein Bild nicht fokussierbar ist: Die Tastaturreihenfolge bleibt, wie sie ist, und 1.3.2 Bedeutungstragende Reihenfolge ist erfüllt, weil gerade der Quelltext die sinnvollere Reihenfolge trägt. Sobald order dagegen Links oder Buttons verschiebt, läuft die Fokusreihenfolge der optischen davon. Das ist der Verstoß gegen 2.4.3 Fokus-Reihenfolge, vor dem Flexbox-Anleitungen zu Recht warnen. Für das Kartenraster selbst ist meist Grid das passende Werkzeug.

Welche Überschriftenebene? Richtig ist die Überschriftenebene, die zur Umgebung passt. Wie sie optisch aussieht, spielt keine Rolle. Stehen die Karten unter einer <h2> „Weiterlesen“, sind es <h3>. Die Größe macht CSS, nicht die Ebene; die Überschriften-Hierarchie bleibt lückenlos.

Häufige Fehler

  • Ganze Karte in ein <a> (verschachtelte Links, geschwätzige Ansage).
  • Klick-<div> mit JS-Handler statt eines echten Links (kein „in neuem Tab“, keine Tastatur).
  • Das ::after an der Karte statt am Link (die nativen Link-Gesten gehen verloren).
  • Kein sichtbarer Fokus auf der Karte, obwohl die ganze Fläche klickbar ist.
  • Doppelter Link zum selben Ziel (Überschrift + „Weiterlesen“).
  • Stretched Link trotz mehrerer Aktionen (die Zweitlinks werden unerreichbar).
  • Bild mit beschreibendem alt, das die Überschrift wiederholt.
  • Text nicht mehr markierbar, ohne dass es nötig wäre.

Häufige Fragen

Wie wird die Karte per Tastatur bedienbar?

Über den echten Link in der Überschrift. Er ist fokussierbar und auslösbar. Den Fokus machst du auf der ganzen Karte sichtbar, am einfachsten mit :has(a:focus-visible). Zusätzlicher tabindex ist überflüssig und schadet.

Funktioniert „In neuem Tab öffnen“ auf der ganzen Karte?

Beim Pseudo-Element-Muster ja: Die Fläche gehört zum <a>, also greifen Mittelklick, ⌘/Strg-Klick und das Rechtsklick-Menü überall. Bei der JavaScript-Variante nur auf der Überschrift.

Dann verzichte auf die voll klickbare Fläche oder hebe den Zweitlink mit position: relative; z-index: 1 heraus und halte Abstand um ihn herum frei, damit kein Fehlklick zur Navigation führt.

Warum lässt sich der Text in der Karte nicht markieren?

Weil das ::after über dem Text liegt und den Mausdruck abfängt. Wo das stört, ersetzt du das Overlay durch den JavaScript-Handler oben und nimmst dafür den Verlust der nativen Link-Gesten in Kauf.

Ist das gut fürs SEO?

Ja. Es bleibt ein normaler, beschreibender interner Link auf der Überschrift (idealer Ankertext, sauber crawlbar). Der „Alles-Link“-Ansatz verwässert den Ankertext dagegen mit dem kompletten Kartentext.

Braucht die Karte ein aria-label?

Nein. Die Karte ist kein Bedienelement, sondern ein Container. Benannt wird der Link, und der heißt bereits wie die Überschrift. Ein zusätzliches Label erzeugt nur eine zweite, konkurrierende Bezeichnung.

Fazit

Klickbare Karten löst du mit dem Stretched-Link-Muster: ein echter Link auf der Überschrift, ein ::after am Link, das die Fläche überzieht, plus ein Fokusrahmen um die ganze Karte über :has(a:focus-visible). Das vermeidet verschachtelte Links und die geschwätzige Ansage des „Alles-Link“-Ansatzes und erhält alle nativen Link-Gesten. Wo der Kartentext markierbar bleiben muss, tauschst du das Overlay bewusst gegen einen kleinen JavaScript-Handler (mit dem Wissen, was du dabei aufgibst). Und sobald eine Karte mehrere Ziele hat, nimmst du echte, getrennte Links und verzichtest auf die voll klickbare Fläche.

Quellen

Gratis E-Book PDF, 37 Seiten HTML & Barrierefreiheit, WCAG & BFSG, GEO & SEO

Das Praxishandbuch für sauberes, zugängliches Web

Das Handbuch behandelt semantisches HTML, Barrierefreiheit, WCAG & BFSG, GEO und SEO praxisnah und am echten Code. Leserinnen und Leser haben es in mehreren Feedbackschleifen verbessert.

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

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