CSS: Zugänglichkeit
Inhalte verstecken mit CSS: display, visibility und sr-only
Welche Technik ein Element richtig versteckt, hängt davon ab, wer es nicht wahrnehmen soll: display: none und das hidden-Attribut verbergen für alle, die sr-only-Klasse nur visuell, aria-hidden="true" nur für Screenreader und inert sperrt die Bedienung.
Verstecken ist im Web eine Frage mit vier Antworten, und die häufigsten Barrierefreiheits-Fehler in diesem Feld entstehen, weil die falsche der vier gewählt wird. Ein Menü, das per opacity: 0 verschwindet, bleibt für die Tastatur bedienbar. Ein Formular-Label mit display: none verschwindet auch aus dem Screenreader. Diese Seite ordnet die Techniken nach der Zielgruppe und zeigt für jede den Code, die Nebenwirkungen und den Anwendungsfall.
Das Wichtigste in Kürze
- Erst die Zielfrage, dann die Technik. Für alle heißt
display: noneoderhidden. Nur visuell heißtsr-only. Nur für Screenreader heißtaria-hidden. -
display: noneundvisibility: hiddenentfernen das Element auch aus dem Accessibility-Tree. Screenreader lesen es in beiden Fällen nicht vor. -
visibility: hiddenlässt die Lücke stehen,display: noneschließt sie. Das ist der sichtbare Unterschied im Layout. -
hidden="until-found"hält versteckten Inhalt für die Seitensuche auffindbar. Für Akkordeons ist der Wert die beste Grundlage. -
Die
sr-only-Klasse versteckt Text nur visuell. Screenreader lesen ihn weiter vor. Auf fokussierbare Elemente gehört sie nur mit:focus-Ausnahme. -
opacity: 0und Off-Screen-Positionen verstecken unvollständig. Das Element bleibt fokussierbar, und der Fokus springt ins Leere. -
Stand September 2026 ist
display: noneanimierbar.@starting-styleundallow-discretemachen Ein- und Ausblendung ohne JavaScript möglich.
Abgrenzung: Diese Seite behandelt das Verstecken mit CSS und HTML. Wann ARIA Semantik entfernen darf und warum sichtbarer Text die bessere Beschriftung ist, steht unter Die erste Regel von ARIA. Inhalt, der durch overflow abgeschnitten statt versteckt wird, behandelt CSS overflow.
Die Zielfrage: Wer soll den Inhalt nicht wahrnehmen?
Jede Versteck-Technik beantwortet eine dieser vier Situationen. Die Tabelle ist die Kurzreferenz, die Abschnitte darunter liefern Code und Begründung.
| Ziel | Technik | Typischer Fall |
|---|---|---|
| Für alle verstecken | display: none, hidden-Attribut, visibility: hidden |
Zugeklappter Tab, geschlossener Dialog |
| Für alle, aber auffindbar | hidden="until-found" |
Akkordeon-Inhalt |
| Nur visuell verstecken | sr-only-Klasse |
Beschriftung neben einem Icon |
| Nur für Screenreader verstecken | aria-hidden="true", alt="" |
Deko-Icon neben sichtbarem Text |
| Bedienung sperren | inert |
Seite hinter einem offenen Dialog |
Für alle verstecken: display, hidden und visibility
display: none
display: none entfernt das Element aus dem Layout und aus dem Accessibility-Tree. Es belegt keinen Platz, bekommt keinen Fokus und wird von keinem Screenreader gelesen. Das ist der richtige Zustand für alles, was gerade nicht gilt: der geschlossene Dialog, der inaktive Tab, das zugeklappte Mobilmenü.
.menue[data-zustand="zu"] { display: none; }
Der Rückweg hat eine Stolperstelle. Wer das Element wieder anzeigt, muss den passenden display-Wert kennen, denn display: block macht aus einem ehemaligen flex-Container einen Block. Robuster ist es, die Sichtbarkeit über eine Klasse oder das hidden-Attribut zu schalten und den display-Wert des sichtbaren Zustands im Stylesheet zu lassen.
Das hidden-Attribut
hidden ist die HTML-Antwort auf dieselbe Aufgabe. Das Attribut markiert im Markup, dass ein Element zurzeit nicht relevant ist, und die Browser setzen es intern als display: none um. In JavaScript ist es als Eigenschaft direkt schaltbar:
<div id="hinweis" hidden>Erst nach dem Absenden sichtbar.</div>
document.getElementById('hinweis').hidden = false;
Die Schwäche des Attributs ist seine Spezifität. Die Browser-Regel [hidden] verliert gegen jede eigene display-Angabe im Stylesheet. Ein nav { display: flex; } überstimmt das hidden-Attribut am selben Element, und das Menü bleibt sichtbar. Die Absicherung ist eine Zeile im eigenen CSS:
[hidden] { display: none !important; }
Das ist einer der wenigen Fälle, in denen !important die richtige Wahl ist, denn das Attribut soll jede Layout-Regel schlagen. Wie der Attributselektor funktioniert, steht unter CSS-Selektoren.
visibility: hidden
visibility: hidden macht das Element unsichtbar und für Screenreader unzugänglich, lässt seinen Platz im Layout aber frei. Die Lücke bleibt sichtbar. Sinnvoll ist das, wenn das Layout beim Umschalten nicht springen soll, etwa bei einem Badge, das je nach Zustand erscheint.
Zwei Eigenheiten unterscheiden visibility von display:
- Kinder können sich zurückholen. Ein Kind mit
visibility: visibleerscheint innerhalb eines versteckten Elternelements.display: nonekennt keinen solchen Weg. -
visibilityist über eine Transition verzögerbar, denn der Wechsel zwischenvisibleundhiddenlässt sich mittransition-delayan das Ende einer Ausblendung legen. Vor@starting-stylewar das der übliche Weg, Ein- und Ausblendungen zu bauen.
Der dritte Wert collapse ist für Tabellen gedacht. An tr, col oder einer Zeilengruppe entfernt er die Zeile oder Spalte samt ihrem Platz, während der Browser die übrigen Spaltenbreiten so weiterrechnet, als wäre sie noch da. Das macht ihn zum schnellen Schalter für ein- und ausblendbare Tabellenspalten. Außerhalb von Tabellen wirkt collapse wie hidden, und bei col-Elementen verhalten sich die Browser uneinheitlich. Wer Spalten zuverlässig schalten will, blendet die Zellen je Spalte über eine Klasse aus, wie es komplexe Datentabellen zeigen.
Die drei Techniken im Vergleich
| Verhalten | display: none |
hidden-Attribut |
visibility: hidden |
|---|---|---|---|
| Platz im Layout | wird freigegeben | wird freigegeben | bleibt belegt |
| Screenreader | liest nicht | liest nicht | liest nicht |
| Fokussierbar | nein | nein | nein |
| Seitensuche (Strg+F) | findet nicht | until-found findet |
findet nicht |
| Ort der Steuerung | Stylesheet | Markup und Skript | Stylesheet |
hidden=“until-found”: versteckt, aber auffindbar
Der Wert until-found löst das älteste Problem zugeklappter Inhalte. Text in einem geschlossenen Akkordeon war für die Seitensuche des Browsers und für Links auf Textfragmente unerreichbar. Ein Element mit hidden="until-found" bleibt durchsuchbar. Findet die Suche einen Treffer darin, entfernt der Browser das Attribut, klappt den Inhalt auf und scrollt hin. Über das beforematch-Event kann ein Skript dabei den Pfeil-Zustand des Akkordeon-Kopfes mitschalten.
<section id="details" hidden="until-found">
<p>Dieser Text ist mit Strg+F auffindbar, obwohl er eingeklappt ist.</p>
</section>
Zwei Einschränkungen begrenzen den Einsatz. Der Browser versteckt solche Inhalte mit content-visibility: hidden statt display: none, das Element bleibt also im Layout als leere Box ansprechbar. Und Safari unterstützt den Wert Stand September 2026 nicht. Dort greift die definierte Rückfallebene der HTML-Spezifikation: Ein unbekannter Wert wirkt wie ein einfaches hidden, der Inhalt ist versteckt und die Suche findet ihn wie bisher nicht. Die Seite funktioniert, nur ohne den Zusatznutzen.
Für Aufklappbereiche ohne Skript bleibt details und summary die erste Wahl, denn Chrome und Edge machen zugeklappte <details>-Inhalte von sich aus suchbar. Der until-found-Weg gehört in eigene Akkordeons und Tab-Oberflächen, die mehr Kontrolle brauchen.
Nur visuell verstecken: die sr-only-Klasse
Der zweite Fall dreht die Richtung um. Der Inhalt soll unsichtbar sein und von Screenreadern trotzdem gelesen werden: die Textalternative neben einem Icon-Button, eine Tabellenbeschriftung, die das Design ausblendet, oder eine Zwischenüberschrift, die nur der Struktur dient. Dafür existiert die Klasse, die je nach Framework sr-only oder visually-hidden heißt:
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
Jede Zeile hat einen Zweck. position: absolute nimmt das Element aus dem Layout. width, height und overflow: hidden schrumpfen es auf einen Pixel, denn ein Element mit Fläche null entfernen manche Screenreader aus der Ausgabe. clip-path: inset(50%) macht den verbliebenen Pixel unsichtbar und ersetzt das gestrichene clip: rect(0 0 0 0) älterer Fassungen. white-space: nowrap verhindert, dass Wörter durch die schmale Box einzeln umbrechen und Screenreader sie ohne Leerzeichen aneinanderhängen. margin: -1px zieht den Restpixel aus dem sichtbaren Bereich.
Von der älteren Off-Screen-Technik mit position: absolute; left: -9999px; ist abzuraten. In Dokumenten mit Rechts-nach-links-Schrift erzeugt sie eine kilometerbreite Scrollfläche, und auf langsamen Geräten kostet die riesige Renderfläche Zeit. Die clip-path-Fassung hat beide Probleme nicht.
<button type="button">
<svg aria-hidden="true" focusable="false"><!-- Lupe --></svg>
<span class="sr-only">Suchen</span>
</button>
Eine Grenze setzt WCAG 2.5.3 Beschriftung im Namen: Sobald ein sichtbarer Text existiert, muss der zugängliche Name ihn enthalten. Versteckter Text darf ergänzen und nie ersetzen, was sichtbar dasteht. Für Formulare gilt die härtere Regel: Sichtbare Labels helfen allen, versteckte nur einem Teil der Nutzenden.
Der Geisterfokus: sr-only auf fokussierbaren Elementen
Ein Link mit sr-only-Klasse bleibt in der Tab-Reihenfolge. Wer durch die Seite tabbt, landet auf einem unsichtbaren Element, und der Fokus verschwindet für Sehende spurlos. Das verletzt WCAG 2.4.7 Fokus sichtbar. Fokussierbare Elemente bekommen die Klasse deshalb nur zusammen mit einer Regel, die sie bei Fokus einblendet. Das bekannteste Muster dafür sind Skip-Links, die als erstes Element der Seite unsichtbar warten und beim ersten Tab sichtbar werden. Wie der eingeblendete Zustand gestaltet wird, steht unter Fokus-Stile.
Nur für Screenreader verstecken: aria-hidden und alt=“”
Der dritte Fall betrifft Inhalte, die sichtbar bleiben und in der Sprachausgabe nur stören: das Deko-Icon neben einem beschrifteten Menüpunkt, die Ziertrennlinie, das Hintergrundbild mit Textinhalt daneben.
aria-hidden="true" entfernt das Element samt Nachfahren aus dem Accessibility-Tree. Für Bilder ist alt="" der ältere, gleichwertige Weg. Beide Angaben ändern an der Darstellung nichts.
<a href="/warenkorb.html">
<svg aria-hidden="true" focusable="false"><!-- Wagen-Icon --></svg>
Warenkorb
</a>
Zwei Regeln verhindern die häufigsten Fehler. aria-hidden="true" gehört nie auf ein Element, das den Fokus bekommen kann, denn dann landet die Tastatur auf einem Element, das der Screenreader verschweigt. Und es gehört nie auf einen Vorfahren von sichtbarem Inhalt, denn es wirkt auf alle Nachfahren und schaltet ganze Seitenbereiche stumm. Wann Bilder leer beschriftet werden und wann sie einen Text brauchen, entscheidet die Seite zu Alt-Texten, die Icon-Fälle behandelt Icons und SVGs.
Bedienung sperren: inert
inert ist der jüngste Baustein und versteckt nichts Sichtbares. Das Attribut nimmt einem Seitenbereich Fokus, Klicks und die Sichtbarkeit für assistive Technologien, während er optisch stehen bleibt. Der Standardfall ist die Seite hinter einem offenen Dialog: sichtbar, abgedunkelt und vollständig gesperrt.
<main inert>
<!-- bleibt sichtbar, ist aber weder klickbar noch fokussierbar -->
</main>
<dialog open><!-- der aktive Dialog --></dialog>
Wer das native <dialog>-Element mit showModal() öffnet, bekommt dieses Verhalten geschenkt, denn der Browser sperrt den Hintergrund von selbst. inert bleibt für Off-Canvas-Menüs, mehrstufige Ansichten und eigene Overlays. Der Zusammenhang steht unter Dialoge und Modals.
Ein- und Ausblenden animieren
Lange galt: display: none ist ein harter Schalter und jede weiche Einblendung braucht JavaScript oder den visibility-Umweg. Stand September 2026 ist das Geschichte, denn alle aktuellen Browser unterstützen transition-behavior: allow-discrete und @starting-style.
.hinweis {
transition: opacity 0.3s, display 0.3s allow-discrete;
}
.hinweis[hidden] {
display: none;
opacity: 0;
}
/* Startwerte für den ersten Frame nach dem Einblenden */
@starting-style {
.hinweis {
opacity: 0;
}
}
allow-discrete erlaubt der Transition, den display-Wechsel mitzunehmen. Beim Ausblenden bleibt das Element bis zum Ende der Transition sichtbar und wechselt erst dann auf none. @starting-style liefert den Startwert für die Gegenrichtung, denn ein Element, das gerade aus display: none kommt, hat sonst keinen Ausgangszustand, von dem aus es animieren könnte.
Ältere Anleitungen und auch aktuelle Treffer in den Suchergebnissen erklären display: none weiterhin für nicht animierbar. Das stimmt seit Ende 2024 in keinem aktuellen Browser mehr. Jede Bewegung dieser Art gehört in eine Abfrage von prefers-reduced-motion, wie sie CSS-Animationen beschreibt.
Barrierefreiheit: worauf es ankommt
Die Versteck-Techniken entscheiden mit darüber, ob eine Seite die Kriterien 1.3.1 Info und Beziehungen, 2.4.3 Fokus-Reihenfolge und 2.4.7 erfüllt. Vier Punkte fassen die Fehlerbilder zusammen:
- Halb versteckt ist die schlechteste Variante.
opacity: 0und Off-Screen-Positionen lassen Elemente fokussierbar und für Screenreader lesbar. Wer vollständig verstecken will, nimmtdisplay: none,hiddenodervisibility: hidden. - Sichtbarkeit und Bedienbarkeit gehören synchron geschaltet. Ein Menü, das nur optisch verschwindet, sammelt beim Durchtabben unsichtbare Fokus-Stopps. Das fällt in jeder Tab-Runde sofort auf.
- Screenreader-Text ist die Ausnahme, sichtbarer Text die Regel. Was allen hilft, soll niemand suchen müssen. Die
sr-only-Klasse ergänzt Kontext und ersetzt keine sichtbare Beschriftung. - Der Accessibility-Tree ist prüfbar. In den Browser-DevTools zeigt der Reiter „Barrierefreiheit“ am Element, ob es im Tree steht. So lässt sich jede der Techniken in Sekunden verifizieren, ohne einen Screenreader zu starten.
Häufiger Fehler in der Praxis
In Audits taucht ein Muster in fast jeder Icon-Navigation auf: Der Button ist visuell selbsterklärend, im Markup steht ein leeres <button> mit einem Hintergrundbild oder einer Icon-Font, und ein zugänglicher Name fehlt. Screenreader sagen dann „Schaltfläche“ ohne jede Angabe, was sie tut. Der Gegenentwurf kostet eine Zeile sr-only-Text oder ein aria-label. Von beiden ist der versteckte Text die robustere Wahl, weil er bei einer automatischen Übersetzung der Seite mitübersetzt wird und aria-label je nach Übersetzer unangetastet bleibt.
Der zweite Dauergast ist das Karussell, das inaktive Folien nur optisch stapelt. Alle Folien bleiben im Accessibility-Tree und in der Tab-Reihenfolge, und Tastaturnutzende tabben durch unsichtbare Links ins Leere. Inaktive Folien brauchen display: none, visibility: hidden oder inert, wie es Slider und Karussells zeigt.
Häufige Fragen
Was ist der Unterschied zwischen display: none und visibility: hidden?
display: none entfernt das Element aus dem Layout, der Platz schließt sich. visibility: hidden lässt den Platz als leere Fläche stehen. Für Screenreader und Tastatur verschwindet das Element in beiden Fällen. Ein weiterer Unterschied liegt in den Kindern: Innerhalb von visibility: hidden kann ein Kind mit visibility: visible wieder erscheinen, aus display: none gibt es diesen Rückweg nicht.
Wie verstecke ich ein Element nur für Screenreader?
Mit aria-hidden="true" am Element, bei Bildern gleichwertig mit alt="". Beide lassen die Darstellung unverändert und entfernen den Inhalt aus der Sprachausgabe. Die Angabe gehört nur auf dekorative Inhalte, nie auf fokussierbare Elemente und nie auf Vorfahren von relevantem Inhalt, denn aria-hidden wirkt auf alle Nachfahren mit.
Wie mache ich Text nur für Screenreader lesbar?
Mit der sr-only-Klasse aus dieser Seite: position: absolute, ein Pixel Größe, clip-path: inset(50%), white-space: nowrap. Der Text verschwindet visuell und bleibt in der Sprachausgabe vollständig erhalten. display: none und visibility: hidden sind für diesen Zweck falsch, weil sie den Text auch aus dem Screenreader entfernen.
Kann ich display: none animieren?
Ja. Mit transition-behavior: allow-discrete wartet der display-Wechsel das Ende der Transition ab, und @starting-style liefert den Startzustand für die Einblendung. Stand September 2026 unterstützen alle aktuellen Browser beides. Für ältere Browser bleibt die Einblendung ein harter Schnitt, der Inhalt bleibt dabei erreichbar. Die Bewegung gehört hinter eine prefers-reduced-motion-Abfrage.
Schadet versteckter Text dem Google-Ranking?
Auf die Absicht kommt es an. Inhalt in Tabs und Akkordeons, den Nutzende aufklappen können, wird normal indexiert. Die sr-only-Klasse für Screenreader-Beschriftungen ist ein dokumentiertes Barrierefreiheits-Muster und unbedenklich. Abstrafungen zielen auf Täuschung, etwa Keyword-Listen in Hintergrundfarbe, die nur für den Crawler existieren. Wer versteckten Text schreibt, der Menschen mit Screenreader hilft, hat nichts zu befürchten.
Verwandte Themen
- Die erste Regel von ARIA erklärt, warum natives HTML vor ARIA-Attributen kommt.
- Skip-Links sind der Praxisfall für visuell versteckte, fokussierbare Elemente.
- Akkordeons zeigen
hidden="until-found"im Komponenten-Zusammenhang. - Fokus-Stile gestalten den Moment, in dem versteckte Elemente sichtbar werden.
- WCAG 1.3.1 Info und Beziehungen ist das Kriterium hinter Struktur und Sichtbarkeit.
Quellen
- The hidden attribute (WHATWG: hidden, until-found und die Rückfallregel)
- visibility (MDN: Werte, Vererbung und Screenreader-Verhalten)
- @starting-style (MDN: Transitionen aus display: none heraus)
- Understanding SC 1.3.1 Info and Relationships (W3C: die normative Grundlage)