SELFHTML wird 30 Jahre alt! → Veranstaltungs-Ankündigung.
CSS/Tutorials/Sichtbarkeit von Elementen
Bei der Darstellung von Webseiten kann es erforderlich werden, bestimmte Teile von der Sichtbarkeit für den Besucher auszuschließen. Dafür gibt es unterschiedliche Werkzeuge in HTML und CSS, und sie haben unterschiedliche Auswirkungen.
Die erste Frage, die sich hier stellt, ist: Sichtbar für wen?
Wir müssen vier Fälle unterscheiden:
- Der Inhalt ist visuell sichtbar und wird von Assistenztechniken beachtet (Standardfall)
- Der Inhalt ist visuell sichtbar, wird aber von Assistenztechniken ignoriert
- Der Inhalt ist visuell verborgen (visually-hidden), wird aber von Assistenztechniken beachtet
(Image Replacement) - Der Inhalt ist visuell und für Assistenztechniken verborgen. Hier gibt es noch einmal zwei Varianten:
- Der Inhalt ist verborgen, beeinflusst aber das Layout
- Der Inhalt ist verborgen und beeinflusst das Layout nicht.
Kompliziert? Ja, leider.
Inhaltsverzeichnis
Vollständige Unsichtbarkeit
Fanngen wir mit dem letzten - vermeintlich einfachsten - Fall an: Ein Element soll vollständig unsichtbar werden, visuell und für Assistenztechniken:
display:none
Die klassische Technik, HTML-Inhalte komplett zu verbergen und auch aus dem Layout herauszuhalten, besteht darin, die CSS-Eigenschaft display eines Elements in seinem style-Attribut auf den Wert none
zu setzen. Durch diese Eigenschaft bleibt das Element im DOM, es wird aber nicht anzeigt, es wird nicht layoutet und Assistenztechniken beachten es nicht.
Das Setzen dieser Eigenschaft hat aber auch Nachteile. Zum einen muss man, wenn man die Sichtbarkeit wiederherstellen will, genau wissen, welches Display-Modell das verborgene Element hat. Inline? Block? Flexbox? Grid? Table? List-Item? Oder man muss ein kompliziertes Stück Code bauen, das zum Verbergen display:none
setzt und zum Sichtbarmachen die display-Eigenschaft aus dem style entfernt.
if (istVerborgen)
element.style.display = "none";
else
element.style.removeProperty("display");
Es wurde auch vorgeschlagen, für die Sichtbarkeit an display
den Wert revert
zuzuweisen. Das funktioniert solange, wie das Element den für die Sichtbarkeit erforderlichen display-Wert aus dem Browser-Stylesheet oder einem Benutzerstylesheet bekommt. Befindet sich der Wert aber in einem Autorenstylesheet, geht er verloren (siehe Kaskade).
Mit HTML 5 wurde das HTML-Attribut hidden eingeführt. Die Browser haben in ihrem eingebauten Stylesheet eine Regel, die so aussieht:
[hidden] {
display:none;
}
Ein Element mit dem Attribut hidden
wird vom Browser ebenfalls nicht angezeigt. Die meisten Browser realisieren es so, dass im Browser-Stylesheet für alle Elemente mit diesem Attribut die Eigenschaft display:none
gesetzt wird. Aus Präsentationssicht besteht deshalb zwischen hidden
und display:none
kein Unterschied.
Die Art, wie das hidden
-Attribut implementiert ist, ist aber auch seine Schwäche. Chris Coyier zitierte in css-tricks.com Monica Dinculescu: (the [hidden]-rule is) less specific than a moderate sneeze
.[1] Sobald für dieses Element eine display-Angabe im Stylesheet erfolgt, wird das hidden
-Attribut überschrieben.
Das kann bedeuten, dass du dein Stylesheet erweitern musst, wenn du die display-Eigenschaft für ein Element gesetzt haast und hidden
verwenden willst.
nav {
display:flex;
}
[hidden] {
display:none !important;
}
Ohne die eigene [hidden]
-Regel würde hidden
auf dem <nav>
-Element nicht funktionieren.
Das hidden
-Attribut kann man in JavaScript sehr einfach setzen, weil es von den HTML-Elementen als Objekteigenschaft bereitgestellt wird:
element.hidden = istVerborgen;
opacity
Mit der Eigenschaft opacity (engl. für Deckkraft) lässt sich über den Alphakanal der Grad der Transparenz eines Elementes steuern. Der Grad der Durchsichtigkeit kann dabei einen Wert zwischen 0% und 100% annehmen.[2]
Im Gegensatz zur visibility
-Eigenschaft, kann die mit Hilfe der opacity
-Eigenschaft festgelegte Durchsichtigkeit bei Nachfahrenelementen nicht wiederhergestellt werden.
Elemente, die die opacity
-Eigenschaft besitzen, erzeugen einen neuen „stacking context“, welcher Einfluss auf die Überlappung verschiedener Elemente besitzt. Bei Elementen mit der visibility
-Eigenschaft ist dies nicht der Fall.
span {
background: #dddd00;
border: 5px solid;
cursor: help;
display: inline-block;
margin: 1em 2em;
outline: 5px solid red;
padding: 1em 2em;
}
.o0 { opacity: 0; }
.o2 { opacity: 0.2; }
.o4 { opacity: 0.4; }
.o6 { opacity: 0.6; }
.o8 { opacity: 0.8; }
.o10 { opacity: 1; }
Das Beispiel besteht aus sechs span-Elementen, die über ihre Klassen unterschiedliche Werte für die Deckkraft haben.
Das erste Element mit der Deckkraft opacity: 0
ist nicht sichtbar; es nimmt jedoch seinen Raum im Elementfluss ein.
Eine derartig festgelegte Deckfähigkeit gilt dabei stets für das gesamte Element, einschließlich border
und outline
. Soll lediglich der Elementinhalt teiltransparent gestaltet werden, so muss auf entsprechende Hintergrundfarben zurückgegriffen werden.
visibility
Die visibility-Eigenschaft gibt es bereits seit CSS 2, und auch sie verbirgt ein Element vor den Augen des Benutzers und vor den Assistenztechniken.
visibility: hidden;
legt fest, dass die von einem Element erzeugte Box vollständig durchsichtig ist. Der Unterschied zu hidden
ist, dass ein Element, das man mit visibility:hidden
verbirgt, immer noch am Layout teilnimmt und der Platz, den es einnehmen würde, frei bleibt. Das kann nützlich sein, weil diese Platzreservierung verhindert, dass die Seite beim Umschalten neu layoutet werden muss und der Inhalt möglicherweise springt.
Um ein Element sichtbar zu machen, setze die visibility
-Eigenschaft auf visible
.
Im Beispiel wird ein Textabsatz wahlweise ausgeblendet (visibility: hidden;
) oder nicht dargestellt. (display: none;
)
Außer visible
und hidden
gibt es noch einen weiteren Wert, den diese Eigenschaft annehmen kann: visibility:collapse
. Dieser Wert gilt ausschließlich für Zeilen, Zeilengruppen, Spalten und Spaltengruppen innerhalb von <table>
-Elementen sowie für Flex-Items und bewirkt, dass die kollabierten Elemente keinen Platz mehr auf dem Bildschirm belegen. Für alle übrigen Elemente wirkt collapse
wie hidden
.
Es gibt eine Sache, die man mit visibility:collapse
erreichen kann, die mit anderen Mitteln kaum möglich ist: Man kann Spalten ausblenden.
<table>
<colgroup>
<col />
<tr><td> 1 - 1 </td><td> 1 - 2 </td><td> 1 - 3 </td><td> 1 - 4 </td><td> 1 - 5 </td></tr>
<tr><td> 2 - 1 </td><td> 2 - 2 </td><td> 2 - 3 </td><td> 2 - 4 </td><td> 2 - 5 </td></tr>
<tr><td> 3 - 1 </td><td> 3 - 2 </td><td> 3 - 3 </td><td colspan="2"> 3 - 4 + 5 </td></tr>
Visuell sichtbar, aber von Assistenztechniken ignoriert
Oft möchte man Webseiten grafisch etwas aufpeppen. Solche Elemente schmücken die Webseite aus, gehören aber nicht zum inhalt und müssen deshalb auch nicht vorgelesen werden.
In vielen Social Media-Netzwerken kann man Text posten - diesen aber leider nicht formatieren. Vermeintlich schnelle Abhilfe schaffen Online-Generatoren, die die Buchstaben des Alphabets durch ähnlich aussehende Unicode-Glyphen ersetzen.
Während ein Sehender diese Glyphen als ähnlich erkennt, sind sie für Screenreader ohne Bedeutung und werden ignoriert!
Mit aria-hidden="true" kann man rein dekorativen Text vor Screenreadern verstecken:
<span aria-hidden="true">𝕯𝖊𝖐𝖔𝖗𝖆𝖙𝖎𝖛𝖊 𝕾𝖈𝖍𝖗𝖎𝖋𝖙</span>
role="none"
Bilder können - wenn sie nur Dekorationszwecken dienen und kein Teil des Inhalts sind, mit einer Landmark Role versehen werden, die diesen Zweck anzeigt:
<img src="decorative.png" alt="" role="none">
In ARIA 1.1 wurde für solche Einsatzzwecke die role="none"
eingeführt, die langfristig den Wert presentation
ersetzen soll. Das alt-Attribut wurde ebenfalls gesetzt, aber leer gelassen, um zu zeigen, dass kein Inhalt vorhanden ist, bzw. nichts vorgelesen werden soll.
→ Bilder im Internet - Ziergrafiken
Visuell verborgen, aber von Assistenztechniken beachtet
Buttons und Icons werden oft über grafische Symbole wie das Hamburger-Icon ☰ erkannt. Da Screenreader diese Grafiken nicht interpretieren können, sollte ein Alternativtext hinzugefügt werden – entweder als alt-Attribut bei Bildern, als aria-label oder durch einen eingeblendeten Hilfstext.
Ein eleganterer Ansatz ist jedoch der umgekehrte Weg: Der Button enthält einen verständlichen Text, der visuell versteckt und durch eine Grafik ersetzt wird.
Diese Technik nennt man …
Image Replacement
Unter Image Replacement versteht man das Ersetzen des Inhalts von HTML-Elementen durch Bilder.[3]
Früher boten Bilder mehr Freiheiten, z. B. bei der Typografie, sodass Überschriften und Menü-Elemente nicht mit den dafür vorgesehenen HTML-Elementen, sondern mit eigens in Bildbearbeitungsprogrammen erstellten Grafiken dargestellt wurden. Problem war neben dem hohen Wartungsaufwand (eine Farbänderung musste in Photoshop durchgeführt werden; die geänderte Grafik musste auf den Server hochgeladen werden, etc) auch die mangelnde Zugänglichkeit durch Screenreader, aber auch im web.archive.org, wenn Überschriften nur durch ein nicht mehr vorhandenes Bild dargestellt werden.[4] [5]
Mit CSS kann man diese Quadratur des Kreises erreichen:
- nichtvisuelle Ausgabemedien (Screenreader, Braille Terminal ) geben das Dokument semantisch korrekt aus
- Suchmaschinen erkennen den Inhalt der Webseite
- visuelle Ausgabemedien (Bildschirm, Drucker) stellen stattdessen die Grafik dar
Die Herausforderung ist nicht etwa das Einsetzen des Hintergrundbilds, sondern das optische „Ausblenden“ des Texts, der aber für Suchmaschinen und Screenreader noch auffindbar sein muss:
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
Die Klasse .visually-hidden
setzt alle Festlegungen für Breite und Höhe auf 1px
, und beschneidet dieses Pixel so, dass auch keine border
mehr sichtbar ist, nimmt es mit position: absolute
aus dem Elementfluss. So wird der Text auf dem Bildschirm unsichtbar, bleibt aber für Screenreader erhalten, um die Barrierefreiheit zu gewährleisten.[6]
Der so ausgeblendete Text kann nun durch eine Grafik ersetzt werden.
Das Tutorial SVG/Tutorials/Text bietet viele Anregungen für grafische Texteffekte. Gerade für Anfänger ist das Hantieren mit den ihnen unbekannten Elementen als Inline-SVG eine Herausforderung.
Anwenderfreundlicher ist das Verwenden externer Standalone-SVGs, die dann mittels Image Replacement anstelle des reinen Texts dargestellt werden.
<h1>
<span class="visually-hidden">selfhtml</span>
<img src="Selfhtml-gepunktet.svg" alt="" role="none">
<span> - unsere Punkte sind keine Windpocken!</span>
</h1>
Die Überschrift besteht aus einem span
-Element mit der oben besprochenen Klasse visually-hidden
, die auf Bildschirmen ausgeblendet, durch Screenreader jedoch vorgelesen wird.
Umgekehrt wird die Grafik auf dem Bildschirm angezeigt; durch das leere alt
-Attribut und die role="none"
nicht vorgelesen.
Flyout-Menü
In diesem Beispiel gibt es gleich zwei versteckte Elemente mit der Klasse visually-hidden
:
- Die Navigation kann am Bildschirm einfach überflogen werden, mit assistiven Geräten wird jeder Link vorgelesen. Ein Skip-Link lässt Tastaturnutzer gleich zum Inhalt springen.
- Der (dynamisch erzeugte) Button hat einen span, der die Funktion erklärt. Auf Bildschirmen wird dies durch ein SVG-Icon erreicht, am Screenreader wird der text vorgelesen
<a id="skip-link" class="visually-hidden" href="#content">zum Inhalt</a>
<header>
<h1>
<a href="#"><img src="triangle.svg" alt="Logo"></a>
Triangular Tours
</h1>
<nav>
<button id="toggle" aria-expanded="false" aria-controls="menu">
<span class="visually-hidden">Menu auf- und zuklappen</span>
</button>
<ul>
<li><a aria-current="page">Home</a></li>
<li><a href="#">Seite 2</a></li>
<li><a href="#">Seite 3</a></li>
<li><a href="#">Seite 4</a></li>
<li><a href="#">Kontakt</a></li>
</ul>
</nav>
</header>
Vorteil der Klasse visually-hidden
gegeneüber einem aria-label: Dies würde zwar von Screenreadern vorgelesen, aber nicht übersetzt.[7]
Ausschneiden von UI-Elementen wie Radio-Buttons
Auch bei Radio-Buttons und Checkboxen ist es wichtig, dass Elemente auf dem Monitor zwar visuell versteckt werden - das Standardverhalten, eben die gewünschte Funktionalität eben auch für Screenreader erhalten bleibt:
input {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
In diesem Beispiel wird ein Eingabefeld auf eine Größe von 1x1 Pixel gesetzt und mit position: absolute
aus dem Elementfluss genommen. Damit der so versteckte Radio-Button nicht als schwarzer Punkt am Bildrand erscheint, wird er mit clip ausgeschnitten.
visibility
Mit der Eigenschaft visibility wird festgelegt, ob ein Element sichtbar oder unsichtbar dargestellt wird. Ein unsichtbares Element hat dabei dieselben Auswirkungen auf nachfolgende Elemente wie ein sichtbares Element.
Die Eigenschaft visibility
kann folgende Werte besitzen:
-
visible
: Standardwert; Das Element wird sichtbar dargestellt. -
hidden
: Das Element wird unsichtbar dargestellt. -
collapse
: Eine Tabellenzeile oder -spalte wird ausgeblendet; wirkt bei anderen Elementen wiehidden
-
inherit
: Der Wert dervisibility
-Eigenschaft des Elternelements wird geerbt.
Der Wert der visibility
-Eigenschaft wird automatisch vererbt. Da der Standardwert visible
ist, sind zunächst alle Elemente sichtbar.
Erhält die visibility
-Eigenschaft eines Elements den Wert hidden
, so wird das Element unsichtbar. Genauer: Die von einem Element erzeugten Boxen werden unsichtbar.
#lückentext em { visibility: hidden; }
<h2>Rätsel</h2>
<p id="lückentext">Das Beispiel <em>Lückentext</em> zeigt die Wirkung der
<code>visibility</code>-<em>Eigenschaft</em> anhand von Inline-Elementen.
Die Eigenschaft wirkt aber auch bei <em>Blockelementen</em>.</p>
<h2>Lösung</h2>
<p>Das Beispiel <em>Lückentext</em> zeigt die Wirkung der
<code>visibility</code>-<em>Eigenschaft</em> anhand von Inline-Elementen.
Die Eigenschaft wirkt aber auch bei <em>Blockelementen</em>.</p>
Dieses Beispiel zeigt einen Lückentext, in dem die Textlücken mit Hilfe der visibility
-Eigenschaft unsichtbar gemacht werden. Trotz der Unsichtbarkeit bleibt der von den versteckten Elementen benötigte Platz erhalten.
Die Werte hidden
und collapse
besitzen identische Auswirkungen. Traditionell wird jedoch nur der Wert hidden
verwendet, um Elemente unsichtbar darzustellen, da der Wert collapse
bei Tabellenzeilen und -spalten eine andere Wirkung besitzt als der Wert hidden
.
Tabellenzeilen und -spalten ausblenden
Der Wert collapse
wird verwendet, um Zeilen, Zeilengruppen, Spalten oder Spaltengruppen einer Tabelle auszublenden.
In diesem Fall werden die betroffenen Zeilen oder Spalten nicht einfach unsichtbar gemacht, sondern vollständig ausgeblendet. Das bedeutet, dass der zuvor beanspruchte Platz frei wird, die Tabelle sich aber nicht an die neuen Platzverhältnisse anpasst.
Dieser Vorgang hat noch weitere Auswirkungen: Verläuft z. B. eine Zelle von einer sichtbaren in eine ausgeblendete Spalte, so bleibt der Inhalt der Zelle zwar sichtbar, wird aber an den Grenzen der Spalte abgeschnitten.
td { border: 1px inset gray; }
#information { visibility: hidden; }
#summe { visibility: collapse; }
<h2>Tabelle mit unsichtbarer Zeile</h2>
<table>
<tbody>
<tr><td>Spalte 1</td><td rowspan="2">Spalte 2</td><td>Spalte 3</td></tr>
<tr id="information"><td>Spalte 1</td><td>Spalte 2</td><td rowspan="2">Spalte 3</td></tr>
<tr><td>Spalte 1</td><td>Spalte 2</td></tr>
</tbody>
</table>
<h2>Tabelle mit ausgeblendeter Zeile</h2>
<table>
<tbody>
<tr><td>Spalte 1</td><td rowspan="2">Spalte 2</td><td>Spalte 3</td></tr>
<tr id="summe"><td>Spalte 1</td><td>Spalte 2</td><td rowspan="2">Spalte 3</td></tr>
<tr><td>Spalte 1</td><td>Spalte 2</td></tr>
</tbody>
</table>
Dieses Beispiel zeigt die unterschiedlichen Auswirkungen der visibility
-Eigenschaft auf eine Tabellenzeile: Der von den Zellen benötigte Platz bleibt bei unsichtbaren Zeilen erhalten. Zellen, die in eine unsichtbare Zeile hineinragen, bleiben vollständig sichtbar.
Eine ausgeblendete Zeile dagegen wird „wie sie ist“ aus der Tabelle herausgelöst. Zellen, die in eine ausgeblendete Zeile hineinragen, werden teilweise ausgeblendet, ihr Inhalt bleibt aber identisch vorhanden (vergleiche die Position des Inhalts bei beiden Tabellen). Die Höhe der Zellen wird nicht neu berechnet. Gegebenenfalls kann auf diese Zellen die overflow
-Eigenschaft angewendet werden, um sich überlappende Inhalte zu vermeiden.
collapse
, verarbeiten ihn aber auch bei Tabellenzeilen- und Spalten wie hidden
(Stand November 2016).border-collapse: collapse;
) werden im Mozilla Firefox zwar korrekt ausgeblendet, die von der Tabelle gezeichneten Rahmen bleiben jedoch unverändert bestehen. (Stand November 2016).Siehe auch
Weblinks
- ↑ CSS Tricks: The 'hidden' Attribute is Visibly Weak
- ↑ W3C: opacity
- ↑ Invisible Content Just for Screen Reader Users (WEBAIM)
- ↑ SELF-Forum: OnePager mit skip-to-top-Linkvon Rolf B.
- ↑ The anatomy of visually-hidden (tgpi.com)
- ↑ css-tricks.com Image Replacement 19 Beispiele von 2003 bis heute
Anmerkung: Früher wurde auszublendender Text um 9999px nach außen geschoben, der Text auf transparent bei einer Schriftgröße von 0 gesetzt, …
alles Methoden, bei denen sich Nachteile und Nebenwirkungen zeigten! - ↑ auto-translation of `aria-label` - Do not rely on it! (Adrian Roselli on twitter)