Komponenten · Navigation & Bedienelemente
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 – nicht, indem du die ganze Karte in ein <a> packst. 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
::aftergehö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
| 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.
Das Stretched-Link-Muster
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 – siehe 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 – ein Missverhältnis, das bei der Tastaturbedienung irritiert. :has() ist seit Ende 2023 in allen aktuellen Browsern verfügbar; wer noch ältere unterstützen muss, setzt den Rahmen ersatzweise per .card a:focus-visible { outline-offset: … } großzügig um die Überschrift.
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 – aber die Karte verliert 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 – siehe 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
Zwei 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.
Welche Überschriftenebene? Die, die zur Umgebung passt – nicht die, die optisch richtig aussieht. 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
::afteran 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.
Was, wenn ich Hauptlink und einen kleinen Zweitlink will?
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
- Accessible Cards (Kitty Giraudel – das Pseudo-Element-Muster, Fokusgestaltung und der Umgang mit Zweitaktionen)
- Block Links: The Search for a Perfect Solution (CSS-Tricks – der Vergleich aller vier Ansätze samt Textauswahl-Handler)