HTML-Landmarks in der Praxis: eine Struktur für Screenreader, Suche und KI

Landmarks von Grund auf: implizite Rollen, die Verschachtelungsregeln, das role-Attribut, Benennung, kopierfertige Muster, Checkliste — plus was Extraktoren daraus lesen.

von ·

Beim Schreiben dieses Artikels habe ich als Erstes meine eigene Seite geprüft — die, auf der du gerade liest. Der interessanteste Befund: Sie hatte keine contentinfo-Landmark, obwohl unten ganz offensichtlich ein Footer stand. Der Footer war da, er war als <footer> ausgezeichnet, er sah aus wie ein Footer — aber für einen Screenreader war er keiner.

Das war kein Schludrigkeitsfehler. Es war die Folge einer Regel, die in der Spezifikation steht, die niemand liest, und die auch kein Validator meldet: Ein <footer> wird nur dann zur contentinfo-Landmark, wenn er kein Nachfahre von <article>, <aside>, <main>, <nav> oder <section> ist. In meinem Layout lag er innerhalb von <main> — aus reinen Layoutgründen, damit Flexbox ihn nach unten drückt. Ein Zeichen HTML-Verschachtelung entscheidet darüber, ob eine Seitenregion in der Landmark-Liste eines Screenreaders auftaucht oder nicht.

Es blieb nicht bei diesem einen Fund. Am Ende waren es drei Befunde in fünf Minuten, dazu ein Dutzend namenloser Landmarks — alle behoben, bevor dieser Artikel online ging. Die Fundstellen stehen an den passenden Stellen im Text, weil sie besser erklären als jedes ausgedachte Beispiel, wie diese Fehler entstehen: nicht aus Nachlässigkeit, sondern aus Layout-Entscheidungen, die für sich genommen völlig vernünftig sind.

Genau darum geht es hier. Landmarks sind eines der wenigen Themen, bei dem Barrierefreiheit, Usability, klassisches SEO und die neue Frage, wie KI-Systeme deine Inhalte extrahieren, dieselbe Antwort haben — und bei dem gleichzeitig fast jede Anleitung im Netz die Hälfte der Regeln unterschlägt. Dieser Artikel ist die vollständige Tour: welche Landmarks es gibt, unter welchen Bedingungen sie entstehen, wann das role-Attribut nötig ist und wann es schadet, wie du sie benennst, was Screenreader-Nutzer damit tatsächlich machen (die Zahlen sind ernüchternder als erwartet), was Google dazu sagt — und ein Messergebnis aus dem Extraktions-Pfad der KI-Systeme, das der gängigen Empfehlung direkt widerspricht.

Methodik-Hinweis: Die Regeln in diesem Artikel stammen aus den Primärquellen (WHATWG-HTML, ARIA in HTML, HTML-AAM, ARIA-APG), nicht aus Sekundärliteratur; die Stellen, an denen sich zwei W3C-Dokumente widersprechen, benenne ich ausdrücklich. Das Kapitel zur KI-Extraktion beruht auf einer eigenen Messung, die du unten nachvollziehen kannst, und auf dem gelesenen Quellcode der beiden verbreitetsten Extraktoren.

Was eine Landmark ist — und was sie nicht ist

Eine Landmark ist ein benannter Großbereich einer Seite, den assistive Technik direkt anspringen kann. Nicht mehr und nicht weniger. Der Browser baut aus deinem DOM einen zweiten Baum, den Accessibility-Tree — eine reduzierte Fassung der Seite, in der jedes Element eine Rolle, einen Namen und einen Zustand hat. Screenreader lesen diesen Baum, nicht dein HTML. Landmarks sind die Elemente in diesem Baum, deren Rolle zur Kategorie „landmark" gehört.

Der praktische Effekt: Ein Screenreader kann eine Liste aller Landmarks anzeigen — „Banner, Navigation Hauptmenü, Suche, Hauptbereich, Ergänzend Verwandte Artikel, Fußzeile" — und der Nutzer springt mit einem Tastendruck dorthin. Ohne Landmarks bleibt ihm nur, sich linear durch die Seite zu arbeiten oder über Überschriften zu navigieren.

Drei Abgrenzungen, die häufig durcheinandergehen:

Landmarks sind keine Überschriften. Die Überschriftenhierarchie (<h1><h6>) beschreibt die inhaltliche Gliederung, Landmarks beschreiben die funktionale Aufteilung der Seite. Beides existiert parallel und beides wird genutzt — Überschriften sogar deutlich häufiger, dazu unten mehr. Ein <section> ohne Überschrift ist genauso legitim wie eine <h2> außerhalb jeder Landmark; die beiden Systeme müssen nicht deckungsgleich sein.

Landmarks sind keine Sektionierungselemente. HTML hat mit <article>, <aside>, <nav> und <section> eine eigene Kategorie „sectioning content", die den Gliederungsalgorithmus betrifft. Die Schnittmenge mit den Landmarks ist groß, aber nicht vollständig: <article> ist sectioning content und keine Landmark (die Rolle heißt article und gehört zur Kategorie „document structure"), <main> ist eine Landmark und kein sectioning content.

Landmarks sind kein ARIA-Zauber. Du brauchst in aller Regel kein einziges role-Attribut, um sie zu bekommen. Die passenden HTML-Elemente bringen ihre Rolle mit — das ist der Normalfall und der bessere Weg.

Die W3C-Autorenrichtlinie (ARIA Authoring Practices Guide) formuliert das Ziel so knapp, dass ich es hier wörtlich stehen lasse: alle wahrnehmbaren Inhalte einer Seite in einer ihrer Landmark-Regionen unterzubringen ist „einer der wirksamsten Wege, um sicherzustellen, dass Nutzer assistiver Technik keine Information übersehen". Das ist die eigentliche Leitregel: kein verwaister Inhalt zwischen den Landmarks.

Die acht Landmark-Rollen und ihre HTML-Entsprechungen

ARIA 1.2 definiert genau acht Landmark-Rollen. Nicht sieben, nicht zwölf — acht. Diese Tabelle ist der Kern des Artikels; alles Weitere sind Bedingungen und Sonderfälle.

Rolle HTML-Element Wofür Anzahl pro Seite
banner <header> (auf Body-Ebene) Seitenkopf: Logo, Seitentitel, globale Werkzeuge eine
navigation <nav> Blöcke von Navigationslinks beliebig viele, benannt
search <search> Such- und Filterfunktion i. d. R. eine
main <main> der Hauptinhalt der Seite genau eine
complementary <aside> Ergänzendes, das für sich allein sinnvoll bleibt mehrere möglich, benannt
contentinfo <footer> (auf Body-Ebene) Fußzeile: Impressum, Copyright, Rechtliches eine
form <form> mit Namen ein inhaltlich abgegrenztes Formular mehrere möglich
region <section> mit Namen ein wichtiger Bereich ohne passendere Rolle mehrere möglich

Drei Dinge fallen an dieser Tabelle auf, und alle drei sind wichtiger, als sie aussehen.

Erstens haben zwei Rollen — banner und contentinfo — eine Bedingung im Element-Feld stehen. Zweitens haben zwei weitere — form und region — eine Bedingung, die einen Namen verlangt. Drittens ist region explizit als Auffangrolle beschrieben: Sie ist die Landmark für Bereiche, für die es keine passendere gibt. Wenn du role="region" schreibst, lohnt sich vorher die Frage, ob nicht complementary, navigation oder search gemeint ist.

Was keine Landmark ist, obwohl es oft dafür gehalten wird: <article> (Rolle article), <address> (Rolle group), <hgroup> (Rolle group), <figure>, <details> und jedes <div> ohne Rolle (Rolle generic). Ein <section> ohne Namen ist ebenfalls keine — dazu gleich.

Die Bedingungen, die kaum jemand kennt

Hier liegt der Unterschied zwischen „ich benutze semantisches HTML" und „meine Seite hat tatsächlich die Landmarks, die ich glaube". Die maßgebliche Quelle ist die W3C-Spezifikation ARIA in HTML, die für jedes HTML-Element die implizite ARIA-Semantik festlegt.

Wörtlich aus ARIA in HTML, für <header>:

Wenn kein Nachfahre eines article-, aside-, main-, nav- oder section-Elements oder eines Elements mit role=article, complementary, main, navigation oder region, dann role=banner. Andernfalls role=generic.

Für <footer> gilt derselbe Satz mit contentinfo statt banner. Das heißt konkret:

<body>
  <header>…</header>   <!-- banner -->
  <main>
    <article>
      <header>…</header> <!-- KEINE Landmark -->
      <footer>…</footer> <!-- KEINE Landmark -->
    </article>
    <footer>…</footer>   <!-- KEINE Landmark — Nachfahre von main -->
  </main>
  <footer>…</footer>   <!-- contentinfo -->
</body>

Das ist übrigens sinnvoll: Der Footer eines einzelnen Artikels (Autor, Datum, Tags) ist eben nicht die Fußzeile der Website. Die Regel bewahrt dich davor, für jeden Artikel in einer Übersichtsliste eine eigene contentinfo-Landmark zu produzieren.

Sie beißt aber genau dann, wenn du wie ich <main> als Flex-Container benutzt und den Seiten-Footer hineinlegst, damit er nach unten rutscht. Das Layout stimmt, die Landmark ist weg — und kein Werkzeug meldet dir das als Fehler, weil es keiner ist. Es ist eine korrekt angewandte Regel mit einem Ergebnis, das du nicht wolltest.

Der Ausweg ist eine Zeile: Nicht <main> macht die Spalte, sondern ein Wrapper darum, und <main> und <footer> werden Geschwister. Genau so sieht dieses Layout seit der Recherche zu diesem Artikel aus:

<div class="content-column">   <!-- macht die Spalte, min-height, flex -->
  <main class="flex-1">…</main>
  <footer>…</footer>           <!-- Geschwister → contentinfo -->
</div>

Ein Detail, das gerade in Bewegung ist: Die zweite maßgebliche Spezifikation, HTML-AAM, ordnet dem verschachtelten <header>/<footer> inzwischen nicht mehr generic zu, sondern die neuen Rollen sectionheader und sectionfooter aus dem ARIA-1.3-Arbeitsentwurf (Stand 4. Juni 2026). Für die Praxis ändert das nichts — beide Fassungen sind sich einig, dass es keine Landmark ist. Es ändert nur den Namen dessen, was stattdessen im Accessibility-Tree steht.

<section>: ohne Namen ist es kein Bereich

Ebenfalls wörtlich aus ARIA in HTML:

role=region, wenn das section-Element einen zugänglichen Namen hat. Andernfalls role=generic.

Das ist die am häufigsten übersehene Regel überhaupt, weil <section> das Element ist, das Entwickler aus Gewohnheit für „irgendein Abschnitt" nehmen. Ein nacktes <section> ist für assistive Technik exakt so viel wert wie ein <div>: nichts.

<!-- generic — keine Landmark, kein Nutzen -->
<section>
  <h2>Aktuelle Projekte</h2>

</section>

<!-- region — Landmark mit dem Namen "Aktuelle Projekte" -->
<section aria-labelledby="projekte-titel">
  <h2 id="projekte-titel">Aktuelle Projekte</h2>

</section>

Bevor du das jetzt überall nachrüstest: Der APG rät ausdrücklich zur Sparsamkeit. Wenn jeder Abschnitt eine region ist, ist die Landmark-Liste so lang wie das Inhaltsverzeichnis und hilft niemandem mehr. Nimm region für die zwei, drei Bereiche, die wirklich Sprungziele sein sollen — der Rest darf generic bleiben und wird über die Überschrift gefunden.

<form>: ohne Namen keine Landmark

Gleiche Mechanik: HTML-AAM formuliert es als Anweisung an die Browser — hat ein Formular keinen zugänglichen Namen, wird es nicht als Landmark ausgegeben. Das ist gut so, denn sonst wäre jedes Suchfeld, jedes Newsletter-Kästchen und jeder Logout-Button-im-Formular eine eigene Landmark.

<form aria-label="Newsletter abonnieren">…</form>

Der APG ergänzt: Ein Formular, das der Suche dient, gehört nicht in eine form-, sondern in eine search-Landmark.

<aside>: die Regel, bei der sich die Spezifikationen uneinig sind

Hier wird es unsauber, und ich sage das lieber deutlich, als eine Scheinsicherheit zu produzieren. ARIA in HTML listet für <aside> schlicht role=complementary, ohne Bedingung. HTML-AAM dagegen unterscheidet: auf Body- oder <main>-Ebene complementary; innerhalb von sectioning content (<article>, <aside>, <nav>, <section>) nur dann complementary, „wenn das aside-Element einen zugänglichen Namen hat. Andernfalls generic".

Die praktische Konsequenz ist eindeutig, egal welcher Fassung dein Browser folgt: Gib einem verschachtelten <aside> immer einen Namen. Dann bekommst du in beiden Lesarten dasselbe Ergebnis, und du erfüllst nebenbei die APG-Regel, dass mehrfach vorkommende Landmarks unterscheidbar benannt sein müssen.

<main>: genau eines, sichtbar

Der HTML-Standard ist hier ungewöhnlich streng formuliert:

Ein Dokument darf nicht mehr als ein main-Element haben, für das nicht das hidden-Attribut gesetzt ist.

Mehrere <main> im DOM sind also erlaubt — solange höchstens eines sichtbar ist. Das ist die Ausnahme für Single-Page-Anwendungen, die mehrere Ansichten vorhalten. Dazu kommt eine Verschachtelungsregel: <main> darf nur Nachfahre von <html>, <body>, <div>, <form> (ohne zugänglichen Namen) und autonomen Custom Elements sein. Ein <main> in einem <section> ist ungültiges HTML — und das meldet der Validator tatsächlich.

Leere Landmarks: der Layout-Platzhalter

Der zweite Fund in meinem eigenen Template. In zwei Layouts stand ein leeres Element, ausschließlich damit die Spalten symmetrisch bleiben:

<aside class="hidden xl:block xl:w-56 xl:shrink-0"></aside>

Auf der Startseite und den Standalone-Seiten produzierte das eine complementary-Landmark ohne jeden Inhalt. Ein Screenreader-Nutzer springt sie an und landet im Nichts. Layout-Hilfskonstruktionen gehören in ein <div> — oder, wenn das Element ohnehin nur Platz hält, ganz raus und der Abstand in die CSS-Grid-Definition. Bei mir wurde daraus ein <div>, ebenso bei den vier weiteren <aside>-Wrappern, die hier nur Sidebar und Inhaltsverzeichnis umschlossen: Die Landmark ist in diesen Fällen die <nav> darin, der Wrapper trug nichts bei außer einem weiteren namenlosen Eintrag in der Landmark-Liste.

Der zugehörige Grundsatz: Ein Element wird nicht nach Aussehen gewählt, sondern nach Bedeutung. <aside> heißt „das hier ist inhaltlich ergänzend", nicht „das hier steht rechts".

Das role-Attribut: die erste Regel von ARIA — und ihre Ausnahmen

Die bekannteste Regel der ARIA-Autorenpraxis lautet sinngemäß: Wenn ein natives HTML-Element die gewünschte Semantik und das gewünschte Verhalten schon mitbringt, benutze es, statt ein anderes Element umzuwidmen. Für Landmarks heißt das:

<!-- Nein: redundant -->
<nav role="navigation">…</nav>
<main role="main">…</main>
<aside role="complementary">…</aside>

<!-- Ja -->
<nav>…</nav>
<main>…</main>
<aside>…</aside>

Die redundante Rolle schadet der Barrierefreiheit nicht direkt — sie sagt nur dasselbe zweimal. Sie schadet der Wartbarkeit: Wer <nav role="navigation"> schreibt, hat den Mechanismus nicht verstanden, und beim nächsten Element wird es dann <div role="navigation"> mit fehlender Tastaturbedienbarkeit. Der W3C-WAI-Leitfaden ist eindeutig: HTML-Elemente zuerst, ARIA-Rollen als Rückfallebene für Fälle, in denen HTML nicht geht.

Wann role tatsächlich nötig ist

Vier Situationen, in denen ich das Attribut setze:

1. Es gibt kein passendes HTML-Element. Für role="search" gab es lange keines; heute gibt es <search> (Baseline seit Oktober 2023, breit verfügbar). Wer ältere Browser bedienen muss, findet hier den einzigen halbwegs guten Grund für eine „redundante" Rolle — dazu unten mehr.

2. Bestandscode, den du nicht umbauen kannst. Ein Template-System, das <div class="sidebar"> ausgibt und dir keinen Zugriff auf das Element gibt, wird mit role="complementary" immerhin zur Landmark. Das ist die Rückfallebene, für die ARIA gedacht ist.

3. Du willst die implizite Rolle bewusst überschreiben. Selten, aber es kommt vor: eine <section>, die eigentlich ein Navigationsblock ist, oder ein <form>, das eine Suche ist:

<form role="search" action="/suche">…</form>

Das war jahrelang das kanonische Muster — heute nimmst du dafür <search>.

4. Spezialvokabulare. DPUB-ARIA definiert für digitale Publikationen zusätzliche Rollen wie doc-toc, doc-bibliography, doc-glossary oder doc-index — die ersten beiden Beispiele leiten sich von navigation ab, doc-bibliography und doc-glossary direkt von landmark. Relevant für E-Books und wissenschaftliche Publikationen, nicht für die durchschnittliche Website.

Wann role schadet

Ein falsches role überschreibt die native Semantik vollständig — und zwar auch dann, wenn das Element damit unbedienbar wird:

<!-- Kaputt: der Button ist für assistive Technik ein Link,
     reagiert aber weiterhin nur auf Leertaste statt Enter -->
<button role="link">Weiter</button>

<!-- Kaputt: die Liste verliert ihre Semantik — und die <li>
     erben die presentation-Rolle gleich mit -->
<ul role="presentation">
  <li>…</li>
</ul>

Die zweite Zeile ist die häufigere Falle: role="presentation" (synonym role="none") entfernt die Semantik eines Elements. Auf einem Layout-<table> ist das richtig. Auf einer Navigationsliste kostet es die Ansage „Liste mit 7 Einträgen", die für die Orientierung entscheidend ist.

Und der Klassiker, den ich in fast jedem Audit sehe:

<!-- Nein: role auf dem falschen Element -->
<div role="main">
  <main>…</main>
</div>

Zwei main-Landmarks ineinander. Screenreader melden das als Fehler oder ignorieren eine davon — beides nicht das, was du wolltest.

Benennen: aria-label, aria-labelledby und die „Navigation Navigation"-Falle

Sobald eine Landmark-Rolle mehr als einmal auf der Seite vorkommt, braucht jede Instanz einen eigenen Namen. Der APG sagt es direkt:

Wird eine bestimmte Landmark-Rolle auf einer Seite mehr als einmal verwendet, gib jeder Instanz dieser Landmark einen eindeutigen Namen.

Zwei Wege führen dahin, und sie sind nicht gleichwertig.

aria-labelledby — wenn eine sichtbare Überschrift da ist. Der Name wird aus dem referenzierten Element gezogen. Vorteil: Er ist sichtbar, er wird bei Übersetzungen automatisch mitgeführt, er kann nicht auseinanderdriften.

<nav aria-labelledby="hauptmenue-titel">
  <h2 id="hauptmenue-titel">Hauptmenü</h2>

</nav>

aria-label — wenn keine sichtbare Überschrift existiert. Der Name steht nur im Attribut. Er muss übersetzt werden wie jeder andere UI-String — in einem zweisprachigen Projekt heißt das: in die Sprachdatei, nicht hartkodiert ins Template.

<nav aria-label="Brotkrümelnavigation">…</nav>

Und nun die Regel, gegen die praktisch jede Seite verstößt, die ich mir ansehe. Wieder wörtlich aus dem APG:

Verwende die Landmark-Rolle nicht als Teil des Labels. Zum Beispiel wird eine Navigations-Landmark mit dem Label „Site Navigation" von einem Screenreader als „Site Navigation Navigation" angesagt.

Der Screenreader sagt die Rolle immer dazu. Dein Label ist der unterscheidende Teil, nicht die Beschreibung.

<!-- Nein -->
<nav aria-label="Hauptnavigation">      <!-- "Hauptnavigation Navigation" -->
<aside aria-label="Seitenleiste">       <!-- "Seitenleiste Ergänzend" -->
<search aria-label="Suchbereich">       <!-- "Suchbereich Suche" -->

<!-- Ja -->
<nav aria-label="Haupt">                <!-- "Haupt Navigation" -->
<nav aria-label="Rechtliches">          <!-- "Rechtliches Navigation" -->
<aside aria-label="Verwandte Artikel">  <!-- "Verwandte Artikel Ergänzend" -->

Im Deutschen fühlt sich aria-label="Haupt" seltsam an, weil das Wort allein nicht steht. Zwei brauchbare Auswege: ein inhaltliches Label statt eines funktionalen (aria-label="Bereiche der Wissensdatenbank") oder eine sichtbare, visuell versteckte Überschrift plus aria-labelledby. Der zweite Weg ist der bessere, weil er auch dem Landmark-Menü von Browser-Erweiterungen einen sinnvollen Eintrag gibt.

Ein Sonderfall aus dem APG, der Zeit spart: Navigations-Landmarks mit identischem Linkset — etwa ein Hauptmenü, das oben und unten dupliziert ist — sollen denselben Namen tragen. Der Nutzer erkennt so, dass er nichts Neues findet.

Zum Schluss der Benennung noch eine Regel aus meinem eigenen Projekt, die ich hier hinterlegen will, weil sie an anderer Stelle Schaden anrichtet: Sichtbare Labels von UI-Chrome sind keine Überschriften. Als ich 2026 die Footer-Spaltentitel und die Inhaltsverzeichnis-Titel dieser Seite von <h5> auf <p> umgestellt habe, war der Auslöser ein Sprung H2 → H5 in der Dokument-Outline. Die Lösung war genau das Muster von oben: <p id="…"> als sichtbares Label, aria-labelledby auf der umgebenden Landmark. Die Outline blieb sauber, die Gruppierung blieb für assistive Technik erhalten. Ein Label ist nicht automatisch eine Überschrift.

Das Grundgerüst zum Kopieren

Das hier ist das Skelett, mit dem ich anfange. Es enthält jede Landmark genau einmal, und jede Zeile hat einen Grund.

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Seitentitel — Website</title>
</head>
<body>

  <!-- Erstes fokussierbares Element der Seite -->
  <a class="skip-link" href="#inhalt">Zum Inhalt springen</a>

  <header>                                    <!-- banner -->
    <a href="/" aria-label="Startseite">…Logo…</a>

    <nav aria-label="Haupt">                  <!-- navigation -->
      <ul>
        <li><a href="/leistungen/">Leistungen</a></li>
        <li><a href="/referenzen/">Referenzen</a></li>
      </ul>
    </nav>

    <search>                                  <!-- search -->
      <form action="/suche/" role="search">
        <label for="q">Website durchsuchen</label>
        <input type="search" id="q" name="q">
        <button type="submit">Suchen</button>
      </form>
    </search>
  </header>

  <main id="inhalt" tabindex="-1">            <!-- main -->
    <h1>Seitentitel</h1>

    <nav aria-label="Brotkrümel">             <!-- navigation -->
      <ol>
        <li><a href="/">Start</a></li>
        <li><a href="/blog/">Blog</a></li>
        <li aria-current="page">Dieser Beitrag</li>
      </ol>
    </nav>

    <article>
      <header>                                <!-- keine Landmark: in <article> -->
        <p>Veröffentlicht am <time datetime="2026-08-13">13. August 2026</time></p>
      </header>

      <p>…Inhalt…</p>

      <footer>                                <!-- keine Landmark: in <article> -->
        <p>Autor: …</p>
      </footer>
    </article>
  </main>

  <aside aria-labelledby="verwandtes-titel">  <!-- complementary -->
    <h2 id="verwandtes-titel">Verwandte Beiträge</h2>

  </aside>

  <footer>                                    <!-- contentinfo -->
    <nav aria-label="Rechtliches">            <!-- navigation -->
      <ul>
        <li><a href="/impressum/">Impressum</a></li>
        <li><a href="/datenschutz/">Datenschutz</a></li>
      </ul>
    </nav>
    <p>© 2026 …</p>
  </footer>

</body>
</html>

Die vier Stellen, auf die es ankommt:

  1. <footer> steht außerhalb von <main>. Genau die Stelle aus meiner Einleitung. Willst du ihn per Flexbox nach unten drücken, mach <body> oder einen Spalten-Wrapper zum Flex-Container (min-height: 100dvh, main { flex: 1 }) — dann brauchst du die Verschachtelung nicht.
  2. <aside> steht außerhalb von <main>. Ergänzender Inhalt, der neben dem Hauptinhalt steht, gehört auf dieselbe Ebene. Ein <aside> in <main> ist trotzdem complementary (<main> ist in der Ausschlussliste von header/footer, aber das ist eine andere Regel) — sauberer ist die Trennung.
  3. tabindex="-1" auf dem Sprungziel. Ohne das Attribut setzen manche Browser bei einem Sprunglink zwar den Scroll-Punkt, aber nicht den Tastaturfokus. Der Nutzer landet optisch beim Inhalt und tabbt anschließend wieder durch die Navigation. tabindex="-1" macht das Element programmatisch fokussierbar, ohne es in die Tab-Reihenfolge zu nehmen.
  4. Der Sprunglink ist das erste fokussierbare Element. Er darf visuell versteckt sein, muss aber bei Fokus sichtbar werden — position: absolute; left: -9999px ohne Sichtbarmachung im Fokus ist ein defekter Sprunglink, und laut WebAIM ist jeder zehnte im Netz genau das.

Dazu das minimale CSS für den Sprunglink:

.skip-link {
	position: absolute;
	left: -100vw;
	top: 0;
	z-index: 100;
	padding: 0.75rem 1rem;
	background: Canvas;
	color: CanvasText;
	border: 2px solid CurrentColor;
}

.skip-link:focus-visible {
	left: 0;
}

Ausbaustufen: Suche, mehrere Navigationen, Dashboards, Formulare

Das Grundgerüst trägt eine Inhaltsseite. Vier häufige Erweiterungen.

Die Suche

<search> ist seit Oktober 2023 breit verfügbar und ersetzt das alte <form role="search">. Wichtig sind zwei inhaltliche Regeln aus der MDN-Referenz: Das Element umschließt die Suchfunktion, nicht die Suchergebnisse. Vorschläge und Schnellzugriffe, die Teil der Suche sind, dürfen hinein.

<search>
  <form action="/suche/">
    <label for="suchfeld">Wonach suchst du?</label>
    <input type="search" id="suchfeld" name="q">
    <button type="submit">Suchen</button>
  </form>
</search>

<!-- Ergebnisse: außerhalb, im Hauptbereich -->
<main>
  <h1>7 Treffer für „Landmarks"</h1>

</main>

Zwei Suchen auf einer Seite — global und bereichsintern — brauchen wie alle doppelten Landmarks Namen:

<search aria-label="Website">…</search>
<search aria-label="Innerhalb dieser Dokumentation">…</search>

Mehrere Navigationen

Der Regelfall auf jeder größeren Seite, und die häufigste Quelle namenloser Landmarks. Meine Faustregel: Jede <nav> bekommt beim Schreiben einen Namen — auch dann, wenn es momentan nur eine gibt. Die zweite kommt sowieso.

<nav aria-label="Haupt">…</nav>
<nav aria-label="Brotkrümel">…</nav>
<nav aria-label="Inhalt dieser Seite">…</nav>   <!-- Inhaltsverzeichnis -->
<nav aria-label="Blättern">…</nav>              <!-- Vor/Zurück -->
<nav aria-label="Rechtliches">…</nav>           <!-- im Footer -->

Nicht jede Linksammlung ist eine <nav>. Der HTML-Standard meint damit „größere Blöcke von Navigationslinks". Drei Links im Fließtext sind keine Navigation; eine Liste von zwölf Kategorien schon.

Ein Detail, das erst im Betrieb auffällt: Wenn deine mobile Navigation ein zweites, separat gerendertes Menü ist — Desktop-Sidebar plus mobiler Drawer, wie in meinem Layout — dann stehen beide im DOM, auch wenn eines per CSS ausgeblendet ist. display: none nimmt ein Element zwar aus dem Accessibility-Tree, aber visibility-Tricks und Off-Canvas-Positionierung tun das nicht. Prüfe im Accessibility-Tree, wie viele Navigations-Landmarks tatsächlich ankommen, nicht im Quelltext.

Anwendungen und Dashboards

Bei Oberflächen ohne klassischen „Artikel" ist region die Rolle der Wahl — sparsam eingesetzt, für die Bereiche, zwischen denen Nutzer wirklich springen:

<main>
  <h1>Übersicht</h1>

  <section aria-labelledby="kennzahlen-titel">
    <h2 id="kennzahlen-titel">Kennzahlen</h2>

  </section>

  <section aria-labelledby="aktivitaet-titel">
    <h2 id="aktivitaet-titel">Letzte Aktivität</h2>

  </section>
</main>

Was hier nicht hingehört: Landmarks um modale Dialoge. Der APG stellt klar, dass modale Dialoge ihren Inhalt nicht in Landmarks wickeln sollen — die Modalität selbst sorgt schon für die Abgrenzung.

Formularseiten

Ein Formular wird nur mit Namen zur Landmark, und eine Landmark ist auch nur bei größeren Formularen sinnvoll. Für die innere Gliederung nimmst du <fieldset> mit <legend> — das ist kein Landmark-Mechanismus, sondern der ältere und in diesem Fall passendere:

<form aria-labelledby="bestellung-titel">
  <h2 id="bestellung-titel">Bestellung abschließen</h2>

  <fieldset>
    <legend>Lieferadresse</legend>

  </fieldset>

  <fieldset>
    <legend>Zahlungsart</legend>

  </fieldset>
</form>

Was Screenreader-Nutzer wirklich tun

An dieser Stelle wird es unbequem, und ich halte das für den wichtigsten Abschnitt des Artikels — weil die meisten Landmark-Anleitungen hier eine Behauptung aufstellen, die die Datenlage nicht deckt.

Die WebAIM Screen Reader User Survey #10 (Befragung Dezember 2023/Januar 2024, 1.539 gültige Antworten) hat gefragt, wie Nutzer auf einer langen Seite Informationen finden:

Methode Anteil
Über Überschriften navigieren 71,6 %
Suchfunktion des Screenreaders („Find") 13,6 %
Die Seite durchlesen 6,4 %
Über Links navigieren 4,8 %
Über Landmarks/Regionen navigieren 3,7 %

3,7 %. Landmarks sind die am seltensten genannte primäre Methode. Wer Landmarks als das zentrale Navigationsinstrument von Screenreader-Nutzern verkauft, hat die Zahlen nicht gelesen.

Die zweite Frage derselben Umfrage zeichnet allerdings ein anderes Bild. Auf die Frage, wie häufig sie Landmarks nutzen, wenn welche vorhanden sind, antworteten:

Häufigkeit Anteil
Wann immer verfügbar 17,9 %
Oft 13,9 %
Manchmal 31,5 %
Selten 20,6 %
Nie 16,1 %

Zusammengenommen nutzen also 31,8 % Landmarks regelmäßig — und der Wert steigt wieder, nachdem er von 43,8 % (2014) auf 25,6 % (2021) gefallen war.

Meine Lesart dieser beiden Tabellen: Landmarks sind kein Primärwerkzeug, sondern ein Orientierungswerkzeug. Überschriften beantworten „wo steht, was ich suche?"; Landmarks beantworten „wie ist diese Seite überhaupt gebaut, und wo fängt der Inhalt an?". Das ist eine seltenere, aber wichtigere Frage — sie stellt sich einmal pro Seite, dafür als Erstes. Und die knapp 32 % regelmäßiger Nutzer sind keine Randgruppe.

Wichtiger noch: Landmarks kosten dich fast nichts. Die richtige Elementwahl ist gratis, ein aria-label sind zwanzig Zeichen. Das Aufwand-Nutzen-Verhältnis ist auch bei 3,7 % unschlagbar — nur die Werbebotschaft muss ehrlich bleiben.

Die Tastenkürzel, mit denen das in der Praxis passiert:

Screenreader Nächste Landmark Nächste Überschrift Übersicht
NVDA (Windows) D H NVDA + F7 (Elementliste)
JAWS (Windows) R (Regions Quick Key) H JAWS + F6 (Überschriftenliste)
VoiceOver (macOS) über den Rotor VO + Cmd + H VO + U (Rotor)

Wenn du keinen Screenreader zur Hand hast: Die Browser-Erweiterung Landmarks von matatk (Firefox, Chrome, Edge, Opera, quelloffen) zeigt die Landmarks einer Seite als Menü, springt sie per Tastatur an, hebt sie visuell hervor und hat ein DevTools-Panel mit Best-Practice-Warnungen. Das ist das schnellste Werkzeug, um die Landmark-Struktur einer Seite zu beurteilen, und es kostet dich zwei Minuten Einrichtung.

Usability jenseits von Screenreadern

Landmarks wirken auch dort, wo niemand an Barrierefreiheit denkt.

Sprachsteuerung. Wer per Spracheingabe navigiert, profitiert von benannten Regionen und von der klaren Trennung zwischen Navigation und Inhalt. Die Namen, die du für assistive Technik vergibst, sind dieselben, die hier als Sprachbefehle taugen.

Reader-Modi. Firefox' Lesemodus basiert auf Mozillas Readability-Bibliothek, Safaris Reader auf einem verwandten Ansatz. Beide entscheiden anhand der DOM-Struktur, was Inhalt und was Beiwerk ist. Ob dein Artikel im Lesemodus mit oder ohne die halbe Sidebar erscheint, hängt direkt an deiner Auszeichnung — das messe ich weiter unten nach.

Sprunglinks. Der klassische „Zum Inhalt springen"-Link ist die Landmark-Nutzung für alle, die per Tastatur navigieren — auch ohne Screenreader. Laut WebAIM Million 2026 haben 17,1 % der Startseiten einen solchen Link (2025: 15,3 %), und „jeder zehnte Sprunglink war defekt". Ein Sprunglink, der nicht sichtbar wird oder ins Leere zeigt, ist schlimmer als keiner: Er kostet einen Tabstopp und liefert nichts.

Browser-Erweiterungen und Werkzeuge. Neben der genannten Landmarks-Erweiterung lesen Outline-Werkzeuge, Übersetzungsdienste und Print-Stylesheets die Struktur mit. Je klarer die Regionen, desto besser die automatische Weiterverarbeitung — was direkt zum nächsten Punkt führt.

Und der Nebeneffekt, der am Ende am meisten wiegt: Eine Seite, die sich sauber in Landmarks aufteilen lässt, ist eine Seite mit klarem Aufbau. Ich habe noch kein Projekt gesehen, bei dem der Versuch, die Landmark-Struktur festzulegen, nicht mindestens eine strukturelle Unklarheit im Layout aufgedeckt hätte. Bei mir waren es diesmal drei — Footer in <main>, leerer <aside>, fehlender Sprunglink —, und alle drei waren in einer knappen Stunde behoben.

SEO: was belegt ist und was Folklore

Hier trennt sich Marketing von Nachprüfbarem, deshalb sortiere ich streng.

Was Google sagt

John Mueller von Google hat die Frage mehrfach beantwortet, zitiert nach Search Engine Journal (Juni 2023):

Semantisches HTML hilft dabei, eine Seite zu verstehen. Es ist aber kein magischer Multiplikator, der eine Website höher ranken lässt.

und

Bitte verwendet semantisches HTML. Es ist kein Ranking-Faktor, aber es kann unseren Systemen helfen, eure Inhalte besser zu verstehen.

Dieselbe Nüchternheit findest du in Googles eigenem SEO-Startleitfaden. Dort steht im Abschnitt über Dinge, auf die du dich nicht konzentrieren solltest, zur Reihenfolge von Überschriften:

Überschriften in semantischer Reihenfolge zu haben, ist fantastisch für Screenreader, aber aus Sicht der Google-Suche spielt es keine Rolle, ob du sie in falscher Reihenfolge verwendest.

Das ist ein bemerkenswert klarer Satz, und er gilt sinngemäß für Landmarks: Es gibt keinen dokumentierten Ranking-Faktor „Landmark". Wer dir etwas anderes verkauft, verkauft dir etwas.

Was trotzdem stimmt

Drei Wirkungen sind belegbar, ohne dass ein Ranking-Faktor dafür nötig wäre.

1. Die Trennung von Haupt- und Nebeninhalt ist ein Bewertungskriterium. Googles Richtlinien für Qualitätsbewerter arbeiten seit Jahren mit der Unterscheidung von „Main Content" und „Supplementary Content". Das sind menschliche Bewerter, kein Algorithmus — aber die Kategorie existiert, und alles, was diese Trennung im Markup explizit macht, arbeitet ihr zu statt gegen sie.

2. Snippet-Auswahl und Deep Links profitieren von Struktur. Was Google als Snippet zieht und ob es zu einem Abschnittsanker verlinkt, hängt an der Erkennbarkeit von Inhaltsblöcken. Landmarks sind dabei ein Signal unter vielen — Überschriften und strukturierte Daten sind stärkere.

3. Der indirekte Weg über die Nutzer ist real. Eine Seite, die im Lesemodus, im Vorlesemodus und in Übersetzungsdiensten funktioniert, verliert weniger Besucher. Das ist kein Ranking-Faktor, das ist einfach ein funktionierendes Produkt.

Was Folklore ist

  • <main> sagt Google, was der wichtige Teil ist." Nein — Google hat nie behauptet, <main> besonders zu gewichten, und Mueller hat mehrfach gesagt, dass <section>, <article> und <div> für die Gruppierung von Textabschnitten weitgehend gleich behandelt werden.
  • „Landmarks verbessern das Crawl-Budget." Es gibt keine Quelle dafür.
  • „Semantische Elemente sind ein Rankingfaktor." Ausdrücklich verneint, siehe oben.

Meine Position: Landmarks sind kein SEO-Werkzeug. Sie sind ein Barrierefreiheits- und Struktur-Werkzeug, das SEO nicht schadet und an mehreren Stellen indirekt hilft. Das reicht als Begründung völlig — dafür muss niemand einen Ranking-Faktor erfinden.

GEO: Landmarks im Extraktions-Pfad der KI-Systeme

Und jetzt der interessante Teil, weil hier tatsächlich gemessen werden kann.

Wenn ein KI-System deine Seite verarbeitet — für ein Trainingskorpus, für eine RAG-Pipeline, für die Antwort eines Chatbots mit Websuche —, dann liest fast nie ein Modell das rohe HTML. Dazwischen sitzt ein Extraktor: eine Bibliothek, die aus dem HTML den eigentlichen Text herausschneidet und Navigation, Werbung, Cookie-Banner und Footer wegwirft. Zwei Bibliotheken dominieren dieses Feld: Readability von Mozilla (die Grundlage von Firefox' Lesemodus und zahlreicher HTML-zu-Markdown-Dienste) und trafilatura (der De-facto-Standard in Python-Datenpipelines).

Was diese beiden aus deinem Markup lesen, kann ich nicht nur behaupten — ich kann es im Quellcode zeigen und nachmessen.

Was im Quellcode steht

Readability führt eine Liste von Rollen, deren Elemente beim Extrahieren entfernt werden (Readability.js, Zeile 178 ff.):

UNLIKELY_ROLES: [
  "menu",
  "menubar",
  "complementary",
  "navigation",
  "alert",
  "alertdialog",
  "dialog",
],

Und im Extraktionslauf (Zeile 1141):

if (this.UNLIKELY_ROLES.includes(node.getAttribute("role"))) {
  this.log("Removing content with role " + node.getAttribute("role") + " - " + matchString);
  node = this._removeAndGetNext(node);
  continue;
}

Drei der acht ARIA-Landmark-Rollen — complementary und navigation explizit, search nicht — führen also dazu, dass ein Element aus dem extrahierten Text fliegt. Zusätzlich prüft Readability aria-hidden="true" und wirft entsprechend markierte Knoten ebenfalls weg.

trafilatura geht den umgekehrten Weg: Es hat eine priorisierte Liste von XPath-Ausdrücken, mit denen es den Inhaltsbereich sucht. Ganz oben stehen (trafilatura/xpaths.py):

XPath("(.//article)[1]"),
XPath("""
    (.//*[self::article or self::div or self::main or self::section][
    @role='article' or @id='article' or @id='story' or …
    ])[1]
    """),

XPath("""
    (.//*[self::article or self::div or self::section][
    starts-with(@class, 'main') or starts-with(@id, 'main') or starts-with(@role, 'main')])[1]|(.//main)[1]
    """),

<article> und <main> stehen hier als Elemente drin, ebenso role='article' und role beginnend mit main. Und in der Wegwerf-Liste:

contains(translate(@role, 'N', 'n'), 'nav') or

Beide Bibliotheken lesen also Landmark-Semantik. Nur — und das ist der Punkt — sie lesen sie unterschiedlich.

Die Messung

Ich habe dieselben Absätze in verschiedene Verpackungen gesteckt und durch Readability 0.6.0 (mit jsdom 30.0.1) geschickt. In allen Varianten ist der Beiwerk-Block identisch aufgebaut: drei <p>-Absätze mit demselben Text, keine Klassennamen, keine IDs. Nur der umschließende Container ändert sich.

const wrappers = {
	"<div>":                        ["<div>", "</div>"],
	"<nav>":                        ["<nav>", "</nav>"],
	"<aside>":                      ["<aside>", "</aside>"],
	'<div role="navigation">':      ['<div role="navigation">', "</div>"],
	'<div role="complementary">':   ['<div role="complementary">', "</div>"],
	'<nav role="navigation">':      ['<nav role="navigation">', "</nav>"],
	'<aside role="complementary">': ['<aside role="complementary">', "</aside>"],
};

Das Ergebnis:

Beiwerk verpackt in Beiwerk im Extrakt Artikeltext Zeichen
<div> drin drin 2731
<nav> drin drin 2731
<aside> drin drin 2731
<div role="navigation"> raus drin 1946
<div role="complementary"> raus drin 1946
<nav role="navigation"> raus drin 1946
<aside role="complementary"> raus drin 1946

Lies die ersten drei Zeilen noch einmal. Für Readability macht das <nav>-Element allein keinen Unterschied. Der Code fragt node.getAttribute("role") ab — und ein <nav> ohne role-Attribut liefert dort null. Die implizite ARIA-Rolle, die den Screenreader interessiert, existiert nur im Accessibility-Tree des Browsers; im DOM steht sie nirgends. Eine Bibliothek, die auf jsdom oder einem HTML-Parser arbeitet, sieht sie schlicht nicht.

Damit steht die Standardempfehlung „schreib niemals <nav role="navigation">, das ist redundant" in einem Konflikt, den ich vorher so nicht auf dem Schirm hatte: Für die Barrierefreiheit ist die Rolle redundant. Für diesen Extraktions-Pfad ist sie das Einzige, was zählt.

Ein Nachtrag zur Sorgfalt: In einem ersten, gröberen Testaufbau — bei dem der Beiwerk-Text roh in einem <div> stand statt in <p>-Absätzen — sah es so aus, als würde das nackte <nav>-Element die Navigation entfernen. Das war ein Artefakt: Readability wandelt <div>-Elemente mit reinem Textinhalt in <p> um und bewertet sie damit als Inhaltskandidaten, ein <nav> nicht. Der Unterschied kam also von der <div>-zu-<p>-Umwandlung, nicht von der Landmark-Semantik. Erst der Aufbau oben, in dem alle Varianten identische <p>-Absätze enthalten, isoliert die Wirkung des role-Attributs sauber. Wer misst, muss die Variable isolieren — sonst misst er den Testaufbau.

Was ich daraus ableite

Das Ergebnis gilt für einen Extraktor. trafilatura sucht nach Elementen (.//main, (.//article)[1]) und beachtet role nur für „nav"; für Readability ist es genau andersherum. Weitere Dienste — Jina Reader, Firecrawl und ähnliche HTML-zu-Markdown-Konverter — bauen vielfach auf Readability auf, was dessen Verhalten überproportional gewichtet.

Meine Empfehlung, und ich formuliere sie bewusst als Abwägung statt als Regel:

  1. Immer das semantische Element. <nav>, <aside>, <main>, <footer> — das ist die Grundlage für alles andere und die Voraussetzung für die Landmark im Accessibility-Tree.
  2. Auf <nav> und <aside> der äußeren Seitenstruktur zusätzlich die passende role, wenn dir die saubere Extraktion durch KI-Systeme und Lesemodi wichtig ist. Das sind pro Seite eine Handvoll Attribute, sie sind spezifikationskonform, und sie kosten die Barrierefreiheit nichts.
  3. Nirgendwo sonst. Keine role-Attribute im Fließtext, keine auf Elementen innerhalb des Hauptinhalts, kein role="main" auf <main> (Readability sucht main gar nicht in UNLIKELY_ROLES, und trafilatura findet <main> als Element).

Wer den Aufwand nicht will, lässt Punkt 2 weg und verliert nichts an Barrierefreiheit — nur an Extraktionsqualität in einem Teil der Pipelines. Das ist eine legitime Entscheidung; sie sollte nur bewusst fallen.

Und der ehrlichste Weg, das Extraktionsproblem zu lösen, ist ohnehin ein anderer: den Inhalt zusätzlich direkt als Markdown anzubieten, damit gar nicht erst geraten werden muss. Genau das macht diese Seite mit ihren per-Seite-.md-Spiegeln und der llms.txt — jede Seite hier gibt es unter derselben URL mit .md am Ende, ohne jedes Layout-Rauschen. Landmarks sind die Absicherung für alle, die diesen Weg nicht nehmen.

Dos and Don'ts

Die Kurzfassung des ganzen Artikels als Gegenüberstellung.

✅ Tu das ❌ Lass das
Semantische Elemente nehmen: <header>, <nav>, <main>, <aside>, <footer>, <search> <div role="banner"> schreiben, wenn <header> möglich ist
Genau ein sichtbares <main> pro Seite Zwei main-Landmarks durch <div role="main"> um <main>
Seiten-<footer> außerhalb von <main>, <article>, <section> Den Footer aus Layoutgründen in <main> legen
Jeder <nav> einen Namen geben — auch der ersten Fünf namenlose Navigations-Landmarks ausliefern
aria-labelledby auf eine sichtbare Überschrift, wo eine existiert Namen doppelt pflegen: sichtbare Überschrift und abweichendes aria-label
Labels ohne Rollennamen: aria-label="Rechtliches" aria-label="Hauptnavigation" → „Hauptnavigation Navigation"
<section> nur mit Namen — sonst ist es ein <div> Jeden Abschnitt zur region machen
<search> für die Suche <form role="search"> neu schreiben (Altbestand darf bleiben)
Sprunglink als erstes fokussierbares Element, tabindex="-1" am Ziel Sprunglink, der bei Fokus unsichtbar bleibt
Layout-Platzhalter als <div> Leeres <aside> für die Spaltenbreite
Identisch benannte <nav> für identische Linksets Dieselbe Navigation zweimal unterschiedlich benennen
Im Accessibility-Tree nachsehen Aus dem Quelltext schließen, welche Landmarks entstehen

Häufige Fehler — und drei aus meinem eigenen Template

Die Liste, die ich beim Prüfen abarbeite, in der Reihenfolge der Häufigkeit.

1. Namenlose Mehrfach-Landmarks. Vier <aside> ohne jeden Namen und fünf von neun <nav> ebenso — das war der Ausgangsbefund auf dieser Seite hier. Ein Screenreader sagte dann viermal „Ergänzend" und fünfmal nur „Navigation". Die Landmark-Liste wird dadurch nicht nutzlos, aber sie verliert genau die Eigenschaft, für die sie da ist. Die Korrektur ging in zwei Richtungen: Die vier <aside> waren reine Layout-Wrapper und wurden zu <div>; die <nav>-Elemente haben Namen aus der Sprachdatei bekommen — bewusst ohne das Wort „Navigation" darin, und für Desktop- und Mobil-Variante derselben Linkliste denselben Namen.

2. Der Footer in <main>. Mein Fund Nummer zwei, oben ausführlich beschrieben. Betrifft jedes Layout, das „Sticky Footer" per Flexbox innerhalb des Inhaltscontainers löst. Die Lösung war ein Spalten-Wrapper, der die Höhe übernimmt, damit <main> und <footer> Geschwister werden.

3. Der fehlende Sprunglink. Fund Nummer drei, und der lehrreichste: In meiner eigenen Projektdokumentation stand seit dem Bauplan „Skip-Link als erstes fokussierbares Element" — implementiert war er nie. Eine Anforderung aufzuschreiben und eine Anforderung umzusetzen sind zwei verschiedene Arbeitsschritte, und die Lücke dazwischen fällt nur auf, wenn jemand nachsieht. In diesem Fall war es ein Blogartikel.

4. <section> als Universal-Container. Ohne Namen bringt es exakt nichts und suggeriert Struktur, die im Accessibility-Tree nicht ankommt.

5. Inhalt außerhalb aller Landmarks. Der Cookie-Banner zwischen </header> und <main>, der Zurück-nach-oben-Button hinter </footer>, das Modal am Ende des <body>. Der APG will alle wahrnehmbaren Inhalte in Landmarks — verwaiste Elemente findet nur, wer linear liest.

6. Verschachtelte Top-Level-Landmarks. banner, main, complementary und contentinfo gehören laut APG auf die oberste Ebene und nicht ineinander.

7. Landmarks um Dialoge. Siehe oben: Modale brauchen keine.

8. Die Rolle im Label. „Suchbereich Suche", „Seitenleiste Ergänzend", „Fußzeile Fußzeile".

9. Rollen ohne das dazugehörige Verhalten. role="button" auf einem <div>, ohne tabindex, ohne Tastaturbehandlung. Nicht spezifisch für Landmarks, aber die häufigste ARIA-Katastrophe insgesamt.

10. Zu viele Landmarks. Ein Dutzend region-Landmarks ist genauso unbrauchbar wie keine. Die Landmark-Ebene ist eine Übersicht, kein Inhaltsverzeichnis.

Zum Maßstab, wie verbreitet der Grundzustand ist: Der WebAIM-Million-Report vom Februar 2026 hat die Startseiten der Top-1.000.000-Websites geprüft. 84,3 % hatten mindestens eine Region beziehungsweise ARIA-Landmark (2025: 80,5 %). Ein <main>-Element oder eine main-Landmark fand sich auf 46,1 % (2025: 42,6 %), eine search-Landmark auf 18,8 % (2025: 16,6 %). Die Hälfte des Webs hat also keinen ausgezeichneten Hauptbereich. Die Richtung stimmt, das Niveau nicht.

Testen: Werkzeuge und ein Prüfskript

Landmarks lassen sich nicht am Quelltext beurteilen, weil die impliziten Rollen erst im Accessibility-Tree entstehen. Vier Wege, die ich nutze:

1. Der Accessibility-Tree in den DevTools. In Chrome und Edge: Elements-Panel → Reiter „Accessibility" → „Full-page accessibility tree". In Firefox gibt es ein eigenes „Barrierefreiheit"-Panel mit einer Filterung nach Landmarks. Das ist die verbindliche Quelle: Was hier nicht als Landmark steht, ist keine.

2. Die Landmarks-Erweiterung. Siehe oben — schnellster Weg zu einem Überblick, inklusive DevTools-Panel mit Warnungen.

3. Automatische Prüfer. axe DevTools, Lighthouse und WAVE prüfen einen Teil der Regeln: doppelte Landmarks, region ohne Namen, Inhalt außerhalb von Landmarks. Was sie nicht finden, ist der Footer in <main> — denn das ist kein Verstoß, sondern eine korrekt angewandte Regel mit unerwünschtem Ergebnis. Verlass dich nicht auf grüne Häkchen.

4. Ein Skript für den Bestand. Für den Überblick über viele Seiten reicht mir eine grobe Zählung im gebauten HTML — genau die, mit der ich die Zahlen dieses Artikels erhoben habe:

# Landmark-Elemente je Seite zählen
f=_site/blog/html-landmarks/index.html
for t in nav main aside footer header article section form search; do
  n=$(grep -oE "<${t}[[:space:]>]" "$f" | wc -l)
  printf "%-8s %s\n" "$t" "$n"
done

# Wie viele <nav> haben einen Namen?
grep -oE '<nav[^>]*aria-label' "$f" | wc -l

# Leere Landmarks aufspüren
grep -oE '<(aside|nav|section)[^>]*></(aside|nav|section)>' "$f"

Das ersetzt keinen Accessibility-Tree, findet aber in Sekunden die groben Ausreißer: Seiten mit sechs namenlosen <nav>, leere <aside>, fehlende <main>. Für die Detailprüfung gehst du danach in die DevTools.

Eine Sache, die dir kein Werkzeug abnimmt: die Frage, ob deine Landmark-Aufteilung inhaltlich stimmt. Ob dieser Block wirklich ergänzend ist oder doch zum Hauptinhalt gehört, ob diese Linksammlung Navigation ist oder Fließtext — das ist eine redaktionelle Entscheidung, keine technische.

Frameworks und CMS: die Realität

Kurz, weil die Situation überall ähnlich ist.

WordPress-Blockthemes liefern über theme.json und die Block-Templates in der Regel brauchbare Landmarks: Der Gruppen-Block kennt HTML-Elemente wie <main>, <aside> und <section>, die Navigationsblöcke rendern <nav>. Die typische Lücke sind die Namen — mehrere Navigationsblöcke landen ohne aria-label im Markup. Prüfen lohnt sich vor allem bei Header- und Footer-Templates.

Bootstrap und Tailwind sind zu Landmarks vollständig neutral: Sie liefern Klassen, keine Semantik. <div class="navbar"> bleibt ein <div>. Die Beispiele in der Bootstrap-Doku benutzen zwar <nav class="navbar">, aber niemand hindert dich daran, das zu übernehmen und in den eigenen Komponenten wieder <div> zu schreiben.

React, Vue, Svelte und die zugehörigen Meta-Frameworks bringen dieselbe Neutralität mit — plus ein spezifisches Risiko: Layout-Komponenten, die per Fragment oder Wrapper-<div> verschachteln, produzieren leicht ungewollte Verschachtelungen. Genau das Problem, das meinen Footer die contentinfo-Rolle gekostet hat. Bei Client-seitigem Routing kommt hinzu, dass der Fokus nach einem Seitenwechsel irgendwo stehen bleibt; ein <main tabindex="-1">, auf das nach jeder Navigation programmatisch fokussiert wird, ist dort die etablierte Lösung.

Statische Generatoren — Eleventy, Astro, Hugo — haben den Vorteil, dass das Ergebnis-HTML direkt prüfbar ist. Das Skript aus dem vorigen Abschnitt läuft über das gesamte _site/-Verzeichnis und findet Ausreißer über alle Seitentypen hinweg.

Die gemeinsame Lehre: Kein Framework schenkt dir Landmarks, und jedes Layout-System kann dir welche wegnehmen. Der Ort, an dem du hinsehen musst, ist immer das ausgelieferte HTML.

Die Checkliste zum Kopieren

Zum Übernehmen in dein Review-Dokument, Pull-Request-Template oder Ticket-System:

## Landmark-Review

### Grundgerüst
- [ ] Genau ein sichtbares `<main>` vorhanden
- [ ] `<main>` ist nur Nachfahre von `html`, `body`, `div` oder `form` (ohne Namen)
- [ ] `<header>` der Seite ist direktes Kind von `<body>``banner`
- [ ] `<footer>` der Seite liegt NICHT in `<main>`/`<article>`/`<section>`/`<aside>`/`<nav>``contentinfo`
- [ ] Sprunglink „Zum Inhalt springen" ist das erste fokussierbare Element
- [ ] Sprungziel hat `tabindex="-1"` und wird bei Fokus sichtbar
- [ ] Kein wahrnehmbarer Inhalt außerhalb aller Landmarks (Cookie-Banner, Buttons, Modale prüfen)

### Benennung
- [ ] Jede `<nav>` hat `aria-label` oder `aria-labelledby`
- [ ] Jedes `<aside>` hat einen Namen, wenn mehr als eines existiert
- [ ] Kein Label enthält den Rollennamen („Navigation", „Suche", „Fußzeile", „Ergänzend")
- [ ] `aria-labelledby` zeigt auf eine tatsächlich existierende, sichtbare Überschrift
- [ ] Navigationen mit identischem Linkset tragen denselben Namen
- [ ] Labels liegen in der Sprachdatei, nicht hartkodiert (bei mehrsprachigen Seiten)

### Bedingte Rollen
- [ ] Jede `<section>`, die eine Landmark sein soll, hat einen zugänglichen Namen
- [ ] Jedes `<form>`, das eine Landmark sein soll, hat einen zugänglichen Namen
- [ ] Verschachtelte `<aside>` haben einen Namen (Spezifikationen sind hier uneins)
- [ ] Suche nutzt `<search>` statt `<form role="search">`

### Sauberkeit
- [ ] Keine redundanten Rollen im Fließtext (`<nav role="navigation">` nur bewusst, s. u.)
- [ ] Keine leeren Landmarks (Layout-Platzhalter sind `<div>`)
- [ ] Keine verschachtelten Top-Level-Landmarks (banner/main/complementary/contentinfo)
- [ ] Keine Landmarks um modale Dialoge
- [ ] Keine `role="presentation"`/`role="none"` auf Navigationslisten
- [ ] Höchstens eine Handvoll `region`-Landmarks pro Seite

### Extraktion (optional, für KI-/Lesemodus-Optimierung)
- [ ] Äußere `<nav>` tragen zusätzlich `role="navigation"`
- [ ] Äußere `<aside>` tragen zusätzlich `role="complementary"`
- [ ] `<main>` und `<article>` sind als Elemente vorhanden (trafilatura sucht danach)
- [ ] Alternativ/ergänzend: Markdown-Fassung der Seite ausliefern

### Verifikation
- [ ] Accessibility-Tree in den DevTools geprüft (nicht nur den Quelltext)
- [ ] Landmark-Liste mit Screenreader oder Landmarks-Erweiterung durchgegangen
- [ ] Automatischer Prüfer (axe/Lighthouse/WAVE) ohne Landmark-Befunde
- [ ] Mobile Variante geprüft — doppelt gerenderte Menüs zählen doppelt

FAQ

Brauche ich <section> überhaupt? Nur mit Namen, und nur für Bereiche, die echte Sprungziele sein sollen. Ohne Namen ist <section> identisch mit <div> — dann nimm gleich <div>, das ist ehrlicher.

Ist <article> eine Landmark? Nein. <article> hat die Rolle article aus der Kategorie „document structure". Screenreader können Artikel trotzdem anspringen, aber in der Landmark-Liste steht <article> nicht.

Darf ich mehrere <main> haben? Im DOM ja, sichtbar nein. Der HTML-Standard verlangt, dass höchstens ein <main> ohne hidden-Attribut existiert. Für Single-Page-Anwendungen mit vorgehaltenen Ansichten ist das die vorgesehene Lösung.

Was ist mit <header> und <footer> innerhalb von <article>? Die sind korrekt und sinnvoll — sie sind nur keine Landmarks. Nach aktuellem HTML-AAM bekommen sie die Rollen sectionheader/sectionfooter aus ARIA 1.3, nach ARIA in HTML generic. In beiden Fällen: keine Landmark, kein Sprungziel.

Soll ich role="navigation" auf <nav> setzen oder nicht? Für die Barrierefreiheit: nein, redundant. Für die Extraktion durch Readability-basierte Werkzeuge: ja, weil nur das Attribut im DOM steht. Meine Empfehlung ist der Kompromiss aus dem GEO-Kapitel — auf den äußeren Struktur-Elementen ja, sonst nein.

Zählt ein per CSS ausgeblendetes Menü als Landmark? display: none und visibility: hidden nehmen ein Element aus dem Accessibility-Tree, Off-Canvas-Positionierung (left: -100vw, transform) nicht. Ein mobiler Drawer, der nur verschoben ist, bleibt eine Landmark — auf dem Desktop zusätzlich zur Desktop-Navigation.

Wie viele Landmarks sind zu viele? Es gibt keine Zahl in der Spezifikation. Meine Faustregel: Wenn die Landmark-Liste länger ist als das, was du jemandem am Telefon über den Aufbau der Seite erzählen würdest, sind es zu viele.

Helfen Landmarks beim Ranking? Nein. Google hat das ausdrücklich verneint. Sie helfen beim Verstanden-Werden — von Screenreadern, Lesemodi und Extraktoren. Das ist ein anderes und, wie ich finde, besseres Argument.

Was ist mit aria-current? Kein Landmark-Attribut, aber der natürliche Partner: aria-current="page" markiert den aktiven Eintrag innerhalb einer Navigations-Landmark. Ohne das ist auch die schönste <nav> orientierungslos.

Und role="region" gegen <section aria-label> — was ist besser? Identisch im Ergebnis. Nimm <section> mit Namen, weil das Element ohnehin da ist und die Regel dann nur an einer Stelle steht.

Fazit

Landmarks sind billig und werden trotzdem meistens falsch gemacht. Das liegt nicht an ihrer Komplexität — es sind acht Rollen —, sondern daran, dass die entscheidenden Regeln Bedingungen sind, die kein Validator prüft und die am Quelltext nicht abzulesen sind.

Die drei Sätze, die ich mir merken würde, wenn ich mir nur drei merken dürfte:

  1. Verschachtelung entscheidet. <header> und <footer> sind nur auf Body-Ebene Landmarks. Ein Layout-Container zu viel, und die Region verschwindet — ohne Fehlermeldung, ohne Warnung, ohne dass es jemandem auffällt.
  2. Ohne Namen keine Landmark, und mit falschem Namen keine gute. <section> und <form> brauchen einen zugänglichen Namen, um überhaupt zu zählen; mehrfach vorkommende Landmarks brauchen unterscheidbare Namen, um zu nützen; und in keinem dieser Namen darf die Rolle noch einmal vorkommen.
  3. Die implizite Rolle steht nicht im DOM. Sie entsteht erst im Accessibility-Tree des Browsers. Alles, was auf einem HTML-Parser arbeitet — Extraktoren, Lesemodi, KI-Pipelines —, sieht sie nicht. Das ist der Grund, warum das vermeintlich überflüssige role-Attribut in einem Teil dieser Werkzeuge den Unterschied macht.

Was mich beim Schreiben am meisten überrascht hat, steht in der ersten Zeile: Ich habe angefangen, meine eigene Seite zu prüfen, und drei Befunde in fünf Minuten gefunden — eine fehlende Footer-Landmark, ein leeres <aside> und einen Sprunglink, der seit dem Bauplan dokumentiert und nie gebaut wurde. Keiner davon war ein Fehler im Sinne eines Werkzeugs. Alle drei waren Fehler im Sinne der Nutzer. Und alle drei waren in einer knappen Stunde behoben — das ist der eigentliche Punkt: Der Aufwand liegt im Hinsehen, nicht im Reparieren.

Nimm dir die Checkliste, öffne den Accessibility-Tree deiner wichtigsten Seite und sieh nach, welche Landmarks tatsächlich ankommen. Das dauert fünf Minuten, und ich wette, du findest auch etwas.

Glossar

Begriffe, die im Text vorkommen und dort den Satz überladen hätten.

Begriff Bedeutung
Accessibility-Tree Der zweite Baum, den der Browser neben dem DOM aufbaut: jedes Element mit Rolle, Namen und Zustand. Screenreader lesen ihn, nicht das HTML.
ARIA Accessible Rich Internet Applications — W3C-Spezifikation für Attribute, die Rolle, Zustand und Beziehungen von Elementen für assistive Technik beschreiben.
ARIA in HTML W3C-Spezifikation, die für jedes HTML-Element festlegt, welche ARIA-Rolle es implizit hat und welche Attribute erlaubt sind.
APG ARIA Authoring Practices Guide — der Autorenleitfaden des W3C mit Mustern und Regeln für den Einsatz von ARIA.
DPUB-ARIA ARIA-Erweiterung für digitale Publikationen mit Rollen wie doc-toc oder doc-bibliography.
GEO Generative Engine Optimization — die Optimierung von Inhalten für generative KI-Systeme statt für klassische Suchergebnisseiten.
HTML-AAM HTML Accessibility API Mappings — die Spezifikation, die beschreibt, wie Browser HTML-Elemente an die Accessibility-APIs des Betriebssystems weiterreichen.
jsdom JavaScript-Implementierung des DOM für Node.js — erlaubt es, HTML ohne Browser zu parsen und zu manipulieren.
Landmark Eine Region der Seite, die assistive Technik direkt anspringen kann. Acht Rollen in ARIA 1.2.
RAG Retrieval-Augmented Generation — Verfahren, bei dem ein Sprachmodell vor der Antwort passende Dokumente aus einer Datenbasis nachschlägt.
Readability Mozillas Bibliothek zur Extraktion des Hauptinhalts aus HTML; Grundlage von Firefox' Lesemodus und vieler HTML-zu-Markdown-Dienste.
Rotor VoiceOvers Navigationsmenü (VO + U), über das sich Überschriften, Links, Landmarks und andere Elementtypen einer Seite auflisten lassen.
sectioning content HTML-Kategorie aus <article>, <aside>, <nav> und <section>, die den Gliederungsalgorithmus des Dokuments betrifft.
trafilatura Python-Bibliothek zur Text- und Metadatenextraktion aus Webseiten; verbreitet in Datenpipelines für Sprachmodelle.
Zugänglicher Name Der Text, mit dem assistive Technik ein Element benennt — aus Inhalt, aria-label, aria-labelledby, <label> oder title berechnet.

Aus diesem Blog: