JavaScript/Tutorials/zugängliches Akkordeon

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Unter einem Akkordeon (engl. accordion) versteht man einen Aufklappmechanismus, der nur einen Teilbereich der Seite darstellt und erst durch die Interaktion des Benutzers (click, touch) oder eine Tastaturbedienung weitere Teilbereiche aufschiebt und somit sichtbar macht.

Viele mit jQuery vorgefertigte, aber auch rein CSS-basierte Beispiele haben den Nachteil, dass sie nicht zugänglich, d.h. auch mit der Tastatur bedienbar sind. In diesem Tutorial lernen Sie, wie Sie ein Akkordeon entwickeln, dessen einzelne Bereiche mit der Tab-Taste angesteuert werden können.

Beachten Sie:
Bevor Sie diese Technik auf Ihrer Webseite übernehmen, sollten Sie sich aber über die Nachteile eines Akkordeons im Klaren sein:

Inhalte sind

  • nicht sofort ersichtlich und
  • (mindestens) einen Klick, Wischer oder Tastendruck vom Nutzer Ihrer Seite entfernt.

Anwendungsbeispiel[Bearbeiten]

Eigentlich erfüllt das details-Element genau die Anforderungen an ein Akkordeon und ist in allen unterstützten Browsern zugänglich, d.h. auch mit der Tastatur zu öffnen und zu schließen. Allerdings wird es vom IE und älteren Firefox-Versionen noch nicht unterstützt.

Im folgenden Beispiel wird auf das details-Element verzichtet und stattdessen seine Funktionalität mit JavaScript nachgebaut. Die Auszeichnung der einzelnen Zustände erfolgt mit ARIA-Attributen.

HTML[Bearbeiten]

Beispiel
<main id="accordion">
  <button aria-expanded="true">Section 1</button>
  <div aria-hidden="false">
    <p>Inhalt 1</p>
  </div>

  <button aria-expanded="true">Section 2</button>
  <div aria-hidden="false">
    <p>Inhalt 2</p>
  </div>

  <button aria-expanded="true">Section 3</button>
  <div aria-hidden="false">
    <p>Inhalt 3</p>
  </div>
Das Akkordeon besteht aus Buttons und einem dazugehörenden div. Jeder Button erhält ein aria-expanded-Attribut, dass den jeweils geschalteten Zustand anzeigt, was auch mit CSS sichtbar gemacht wird.
Die divs erhalten ein aria-hidden-Attribut.
Beachten Sie: Inhalte, die mit aria-hidden=true" ausgezeichnet sind, sind nicht lesbar.
Deshalb sind im Urzustand alle Elemente aufgeklappt und werden erst mit JavaScript geschlossen, indem das aria-hidden-Attribut bei der Initialisierung auf false gesetzt wird, sodass die Inhalte auch ohne JavaScript gelesen werden können.

Wieviel aria soll's denn sein?[Bearbeiten]

Das oben schon erwähnte details-Element hätte ein bestimmtes Standardverhalten. Wenn Sie nun ein Akkordeon nachbauen, sollen Screenreader und Nutzer dieses Verhalten nachvollziehen können. Deshalb erhalten die Zustände anstelle von reinen Klassennamen nun standardisierte ARIA-Attribute.

Wie bei jeder Verbesserung kann diese auch zu weit getrieben werden:

Beispiel
<main id="accordion">
  <button aria-expanded="true" aria-controls="collapsible-0">Section 1</button>
  <div id="collapsible-0" aria-hidden="false">
    <p>Inhalt 1</p>
  </div>
  ...
</main>
Das Akkordeon besteht aus Buttons und einem dazugehörenden div. Um diesen Zusammenhang auch für Screenreader klarzustellen, erhalten die Buttons ein aria-controls-Attribut, dass auf die id des dazugehörenden divs verweist.

Dieses aria-controls-Attribut wird jedoch nur von JAWS unterstützt und ist, da das dazugehörende div direkt auf den Button folgt, auch nicht nötig.

Auch eine landmark role button role="button" ist nicht nötig, da dies dem Standardverhalten des Elements entspricht.[1]


CSS der Buttons[Bearbeiten]

Beispiel: Gestaltung der Buttons mit CSS
#accordion button[aria-expanded="true"]:after  {
    content: " \002B";
    color: #777;
    font-weight: bold;
}

#accordion button[aria-expanded="false"]:after  {
    content: " \2212";
}
Um den Schaltzustand der Buttons sichtbar zu machen, erhalten sie im eingeklappten Zustand ein +, das weiteren Inhalt anzeigt.
Im aufgeklappten Zustand wird dies zu einem Minuszeichen.

JavaScript[Bearbeiten]

Die Funktionalität des Beispiels wird erst mit JavaScript erreicht:

Beispiel ansehen …
document.addEventListener("DOMContentLoaded", function () { 
	// alle Elemente mit aria-expanded=true werden zugeklappt
	var acc = document.querySelectorAll('[aria-expanded="true"]'),
		index;
	for (index = 0; index < acc.length; index++) {alert(1);
		acc[index].setAttribute('aria-expanded', false);
		var panel = acc[index].nextElementSibling;
		var hidden = (panel.getAttribute('aria-hidden') == 'false' || false)? true : false ;
    	panel.setAttribute('aria-hidden', hidden);
	}	
	
	//nur ein EventHandler für das gesamte Accordion
    var acc = document.getElementById('accordion');
    acc.addEventListener('click',clickHandler);
    

    function clickHandler(elem) {
    // Wo wurde geklickt?
    var target = elem.target;
    // Toggle den aria-expanded-Zustand
	var state = (target.getAttribute('aria-expanded') == 'false' || false)? true : false ;
    target.setAttribute('aria-expanded', state);
	
    // Aus-/ Einklappen
	var panel = target.nextElementSibling;
	var hidden = (panel.getAttribute('aria-hidden') == 'false' || false)? true : false ;
    panel.setAttribute('aria-hidden', hidden);
	}

});
Beim Laden des Dokuments werden mit querySelectorAll('[aria-expanded="true"]') alle ausgeklappten Elemente selektiert. In einer Schleife wird für diese Elemente mit setAttribute das Attribut aria-expanded auf false gesetzt. Das div mit dem Inhalt erhält ein aria-hidden:true (siehe unten).

Das Akkordion erhält mit addEventListener einen EventHandler, der bei einem Klick die Funktion clickHandler aufruft.
Diese Funktion ermittelt mit target das geklickte Element. Wenn dies ein aria-expanded-Attribut hat, wird der Zustand getoggelt (und damit das oben erwähnte CSS selektiert.

In einem zweiten Schritt wird mit nextElementSibling das Nachbarelement identifiziert und dessen aria-hidden-Attribut getoggelt, dass wiederum über CSS selektiert wird:
[aria-hidden="true"] {
    height: 0;
    transition: height 0.2s ease-out;	
}
 
[aria-hidden="false"] {
    height: 100%;
    transition: height 0.2s ease-out;	
}

Fazit[Bearbeiten]

Da das in Details verwendete summary-Element nur eingeschränkt mit CSS formatierbar ist, bietet sich das hier gezeigte Beispiel an.

Eine Variante wäre ein Akkordeon aus mehreren Elementen, bei denen immer nur eins aufgeklappt ist. Diese ist auch unter dem Begriff Tab Panel bekannt.

Quellen[Bearbeiten]

  1. Inclusive Components (Heydon Pickering): Collapsible Sections 26 October, 2017

Weblinks[Bearbeiten]