Webkrauts Logo

Webkrauts Webkrauts Schriftzug

- für mehr Qualität im Web

Grundregeln für zugängliches JavaScript

Wir haben noch nicht alle älteren Artikel nachbearbeitet. Das bezieht sich in der Regel nur auf die Codebeispiele, die noch nicht optimal dargestellt werden.

Grundregeln für zugängliches JavaScript

Im Zeitalter von Web 2.0 ist der Einsatz von JavaScript und Ajax vielerorts nicht mehr weg zu denken. Dabei liegt es in der Hand des Entwicklers, ob infolge des JavaScript-Einsatzes die Zugänglichkeit einer Seite behindert wird oder nicht. Dirk Jesse stellt dazu heute einen kleinen Best-Practice-Leitfaden vor.

Entwickler haben beim Einsatz von JavaScript einiges zu beachten. Denn HTML & CSS sowie die Browser machen selbst keinerlei technischen Vorgaben bezüglich der Einbindung von JavaScript. Da HTML, CSS und JavaScript außerdem immer in Verbindung stehen, sind auch sprachübergreifende Regeln zu beachten, wenn das eigene JavaScript sowohl funktional als auch barrierefrei sein soll.

Schritt 1: Valides, wohlgeformtes HTML

JavaScript kann nicht heilen, was in HTML & CSS bereits Barrieren für den Nutzer entstehen lässt. Zeichne Deine Inhalte daher sauber aus, verwende sinnvolle HTML-Elemente zur Strukturierung des Layouts. Prüfe, ob die Webseite auch bei deaktiviertem JavaScript und CSS eine übersichtliche Gliederung aufweist und alle Elemente (Navigation, Formulare etc.) benutzbar bleiben.

Schritt 2: Valides und sinnvolles CSS

Wie auch bei HTML solltest Du Validitätschecks Deiner Stylesheets zur Fehlerkontrolle nutzen. Darüber hinaus musst Du natürlich auch in Deinem CSS zunächst dafür Sorge tragen, dass keine unnötigen Barrieren für den Nutzer aufgebaut werden.

Inhalte zugänglich verstecken

Bestimmte Inhalte und/oder Navigationshilfen (z.B. Skiplinks) werden nur dann benötigt, wenn Nutzer die Tastatur zur Navigation verwenden, oder beispielsweise Screenreader nutzen. Diese Elemente gilt es aus dem Sichtbereich des Screendesigns herauszuhalten, sie aber gleichzeitig für den Screenreader zugänglich zu belassen. Um beispielsweise die schon angesprochenen Skiplinks zu verstecken, verwendet man eine absolute Positionierung, um das jeweilige Element aus dem sichtbaren Bereich des Viewports zu schieben. Die folgende CSS-Klasse erledigt das:

.skip {
  position: absolute;
  left: -1000em;
}
Bedienung auch ohne Maus möglich

Viele motorische Behinderungen führen dazu, dass Nutzer statt der Maus alternativen Eingabegeräten verwenden, beispielsweise die Tastatur – davon sprach ich gerade schon. Prüfe daher, ob neben der CSS-Pseudoklasse :hover auch die für Tastaturnutzer wichtige Hervorhebungen durch :focus und :active sinnvolle CSS-Eigenschaften erhalten, um den jeweils aktiven Link auf der Webseite gut sichtbar hervorzuheben. Versteckte Inhalte sollten sichtbar werden, wenn der Focus auf ihnen liegt, daher benötigt die oben beschriebene Klasse .skip noch eine Ergänzung:

.skip:focus,
.skip:active {
  position: static;
  left: 0;
}

Neben der CSS-Pseudoklasse :focus sollte immer auch :active definiert sein, da die verschiedenen Browser die einzelnen Zustände unterschiedlich interpretieren.

Schritt 3: Verfügbarkeit von JavaScript

Die Verfügbarkeit von JavaScript kann nicht vorausgesetzt werden, daher musst Du dafür sorgen, dass Deine Webseite auch ohne JavaScript uneingeschränkt benutzbar ist. Bei Einhaltung der Regeln aus den ersten beiden Schritten, ist dieser Zustand im Regelfall gegeben. Mit JavaScript sollen nun Bereiche der Seite umgebaut oder Elemente dynamisch ergänzt werden. Auch ein Script muss jedoch erst geladen werden, bevor es ausgeführt werden kann, weshalb es sinnvoll ist, möglichst frühzeitig die Verfügbarkeit von JavaScript zu testen und ggf. über CSS auf das Testergebnis zu reagieren, um Elemente gezielt ein- oder auszublenden. Genau diese Aufgabe erledigt folgender Einzeiler, möglichst weit vorn im HEAD-Element der Webseite notiert werden sollte:

<script type="text/javascript">
document.documentElement.className += " js";
</script>

Diese Anweisung sorgt dafür, dass bei Verfügbarkeit von JavaScript automatisch die CSS-Klasse js an das HTML-Element angehangen wird und sich Seitenelemente fortan einfach gestalten lassen:

#container { ... } /*  Styles if JavaScript is not available*/
 .js #container { ... } /* Styles if JavaScript is available */

Schritt 4: Frühzeitiges Starten des Script-Codes

In vielen älteren JavaScript-Büchern und Online-Artikeln wird mit dem Start der Scriptabarbeitung auf den onLoad Event gewartet. Dieser Event wird vom Browser gefeuert, wenn alle Elemente der Seite (HTML, CSS, JavaScript, Bilder ect.) vollständig geladen wurden. Der vollständige DOM-Baum (Document Object Model) steht im Browser jedoch bereits zu einem deutlich früheren Zeitpunkt zur Verfügung, weshalb auch die Abarbeitung von JavaScript deutlich eher starten kann. Die meisten JS-Frameworks bringen hierfür entsprechende Funktionen mit. Bei jQuery ist es die Funktion ready(), welche diese Aufgabe übernimmt.

$(document).ready(function(){
  // do something
  ...
});

Durch den frühzeitigen Start der JavaScript-Applikation bleiben notwendige Umbauten oder Ergänzungen im DOM beim Hinzufügen von Elemente und Verhaltensweisen oder dem Umbau des Quelltextes (Beispiel: Erstellung einer Tab- oder Accordion-Effekten) bei Verfügbarkeit von JavaScript für den Nutzer weitgehend unbemerkt.

Schritt 5: Trennung von Struktur, Layout und Dynamik

Aus der Unsicherheit heraus, dass JavaScript beim Nutzer nicht verfügbar sein muss, ergibt sich die logische Konsequenz, dass Sie Verhaltensregeln Ihrer Webseite, die JavaScript erfordern, auch erst mit JavaScript in Ihre Webseite integrieren. Folgendes Beispiel fand ich in einem Forenthread von 2008 eines bekannten deutschsprachigem HTML-Forum (leicht geändert, um niemanden zu kompromitieren):

<a href="#" onClick="MM_openBrWindow('bilder/01_heu.html','','resizable=no,width=550,height=413')"onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('foto01','','foto_01_over.jpg',1)"><img src="foto_01.jpg" alt="Foto 1" name="foto01" width="300" height="200" hspace="0" vspace="0" border="0" id="foto01" /></a>

Alles klar? Die schon länger dabei sind, werden es vermutlich gleich sehen – Dreamweaver lässt grüßen. Hier gehen gleich mehrere Sachen schief. Zum einen wird hier ein Hover-Effekt mit JavaScipt und den HTML-Event-Handlern onmouseover und onmouseout umgesetzt, obwohl sich dies viel charmanter mit CSS realisieren ließe. Zum anderen enthält dieses Beispiel eine unzugängliche Technik, ein Popup-Fenster zu öffnen. Wie man sieht, befindet sich im href-Attribut des Links keine sinnvolle URL. Ohne JavaScript-Unterstützung bzw. in Screenreadern oder Textbrowsern ist dieser Link absolut unbrauchbar. Das Codefragment — eine Vermischung aus HTML und JavaScript — ist unübersichtlich und bläht den Quellcode unnötig auf, denn es wird in jedem Fall geladen, auch wenn JavaScript deaktiviert oder gar nicht verfügbar ist. Arbeiten Sie daher besser mit Script-Blöcken im HTML-Header Ihrer Webseite (um zumindest die Pflege zu vereinfachen) oder besser, lagern Sie Ihren JavaScript-Code in externe Dateien aus.

Das folgende Codebeispiel basiert auf jQuery und zeigt eine bessere Lösung. Dazu ergänzen wir unseren Link zunächst um das Attribut rel="external".

<a href="http://mydomain.de/popup-content.html" rel="external">Hier gibts weitere Informationen</a>

Mit Hilfe dieses zusätzlichen Attributs, kannst Du beliebige Links Deiner Webseite kennzeichnen, deren URL in einem neuen Fenster geöffnet werden soll. Und nun der JavaScript-Teil, der gleich auch noch exemplarisch die Verwendung des hover-Events zeigt, um auf Wunsch der Webseite noch ein klein wenig Magie hinzuzufügen.

$(document).ready(function(){
  // open this link in a popup window ...
  $('a[rel="external"]').click(function(){
    window.open($(this).attr(href));
    return false;
  });

  // using hover event for a little bit of magic ...
  $('a[rel="external"]').hover(function(){
   // do anything on 'mouseover' ...
   ...

   },function(){
   // do anything else on 'mouseout' ...
   ...

   });
});

Halte Dich also – wann immer möglich – an die Trennung der drei Schichten Struktur (HTML), Layout (CSS) und Verhalten (JavaScript).

Schritt 6: Dynamik kommt und geht mit JavaScript

JavaScript wird dazu verwendet, Webseiten mit dynamischen Effekten zu versehen. Ein Nutzer mit deaktiviertem JavaScript wird von perfekt gestalteten Tabreitern wenig haben, wenn ein Klick darauf nichts bewirkt. Eine einfache und wichtige Regel ist daher: Bedienelemente, die nur in Verbindung mit JavaScript eine Funktion haben, sollten möglichst auch dynamisch mit JavaScript erzeugt, bzw. eingeblendet werden.

Schritt 7: Informiere den Nutzer über Änderungen

Ein weit verbreiteter Irrglaube ist, dass Screenreader mit JavaScript und Ajax nichts anfangen können. Sie können es schon lange — sie wissen es nur nicht. Screenreader kopieren den Inhalt einer Webseite vor der Ausgabe in einen internen Puffer. Nur in bestimmten Situationen (z.B. beim Ausfüllen von Formularen) wird dieser Zwischenspeicher aktualisiert. Das bedeutet, dass Screenreader es meist einfach nicht merken, wenn Seiteninhalte dynamisch manipuliert werden. Hier muss man als Entwickler nachhelfen.

Ein geeignetes Hilfsmittel hierfür ist ein unsichtbares Formularfeld (<input type="hidden value=""/>), in welchem man bei jeder Änderung auf der Webseite auch den Wert des Formularfeldes ändert. Auf diese Weise werden Screenreader dazu veranlasst, ihren Zwischenspeicher zu aktualisieren und somit wiederum per Ajax nachgelandene Inhalte für Screenreader zugänglich. Zusätzlich kann es sinnvoll sein, auch den Focus zu manipulieren, um den Nutzer bewusst auf die Änderungen hinzuweisen. Dazu baut man Sprunganker (<a id="tab1_content" name="tab1_content"></a>) in das Layout ein, denn nur auf Links und Formularfelder lässt sich der Focus setzen. Innerhalb von jQuery stehen für die Manipulation des Focus die Funktionen .focus() und .blur() zur Verfügung.

Weitere Verbesserungen der Zugänglichkeit lassen sich durch die Unterstützung von WAI-ARIA (Accessible Rich Internet Applications) Rollen erreichen, doch das ist ein so umfangreiches Themengebiet, dass ich es hier nur darauf verweisen will.

Fazit

Nach 7 Schritten ist man schon ein ganzes Stück gelaufen. Wie bei vielen Dingen des täglichen Lebens lässt sich die Zugänglichkeit einer Webseite nicht anhand fester Regeln definieren oder gar automatisieren. Es werden immer individuelle Entscheidungen zu treffen sein und wenn man es ernst meint mit der Zugänglichkeit, geht es auch nicht ohne Tests mit verschiedenen Nutzergruppen. Unabhängig davon beschreiben diese 7 Regeln eine Arbeitsweise, die allgemein zu unaufdringlichen und zugänglichen Applikationen führt. Abschließend möchte ich noch auf ein wunderbares, mehrstufiges Tutorial rund um das Thema "Unobtrusive JavaScript" hinweisen, welches Chris Heilmann bereits 2005 veröffentlicht hat und welches nach wie vor uneingeschränkt jedem interessierten Anwender zu empfehlen ist.

Kommentare

Thomas Weise
am 05.12.2008 - 09:06

Interessanter Tip bei 3. mit dem '.js'. Danke.

Permanenter Link

molily
am 05.12.2008 - 12:10

Toller Artikel!

Kleiner Performance-Vorschlag: $('a[rel="external"]') muss nur einmal ausgeführt werden. jQuery erlaubt folgendes Chaining:

$('a[rel="external"]')   .hover(...)   .click(...)

Permanenter Link

Dirk
am 05.12.2008 - 12:28

Nachtrag zu Punkt 2: Ich hatte bewusst hier nur das Notwendigste an CSS-Eigenschaften in die Skiplink-Klasse gepackt - und die große Mehrheit gibt sich damit auch zufrieden.

Nur der aktuelle Safari scheint sich aufgrund eines Bugs dagegen zu sträuben. Um auch im Safari Dinge sauber zu verstecken, ist daher zusätzlich die Eigenschaft top:-1000em erforderlich.

Permanenter Link

molily
am 05.12.2008 - 20:55

Was spricht gegen die erprobte Off-Left-Methode? Deren Eigenschaften sind alle nötig, soweit ich weiß.

Permanenter Link
Dirk Jesse

Dirk Jesse (Autor)
am 05.12.2008 - 21:25

@molily

Was spricht gegen die erprobte Off-Left-Methode? Deren Eigenschaften sind alle nötig, soweit ich weiß.

Das ist zum Teil sicher Geschmacksache, richtet sich aber auch nach den Inhalten, die es zu verstecken gilt.

Ich empfehle mittlerweile, die Eingriffe so gering wie möglich zu halten und daher auch nicht willkürlich Eigenschaften wie width oder height auf Null zu setzen, gleiches gilt für overflow (oder Dinge wie Schriftgröße und Zeilenhöhe auf Null setzen – sieht man auch häufig).

Beim Verstecken ist die Vergabe all dieser Eigenschaften i.d.R. unproblematisch. Beim wieder Erscheinen lassen (.skip:focus, .skip:active), hat man aber unter Umständen plötzlich viel Arbeit, wenn man die Klassen mal nicht nur auf einfachen Fließtext anwendet, sondern beispielsweise auf Seitenelemente mit definierten Geometrien. Denn für das Verstecken von Inhalten ist deren Ausgangsgeometrie egal, beim wieder Erscheinen lassen, muss man sie jedoch wiederherstellen - was u.U. dann recht aufwändig werden kann.

Die absolute Positionierung nach links oben mit ausreichend großen Versatzwerten hat mich bisher nie im Stich gelassen. Daher sehe ich keinen dringenden Grund für weitere zwingende Eingriffe. Sollte ein solcher tatsächlich einmal nötig werden, ist es vermutlich einfacher, diesen dann gesondert zu behandeln.

Permanenter Link

alexander farkas
am 06.12.2008 - 02:45

Etwas mehr kann man schon erwarten - im Jahr 2008. Anfangs wird noch auf Tastaturnutzung hingewiesen, bei der eigentlichen Magie wird dann plötzlich nur noch auf klassische Mausevents gesetzt (geht´s nicht besser).

Ein einfaches Fokusieren mit JS hat bei Screenreadern i.d.R. nur "im Formular"- oder "Applikationmodus" Aussicht auf Erfolg. Sollte i es funktionieren, ist es sowieso keine so gute Idee den User auf einen leeren Link springen zu lassen. Da Screenreader i.d.R. nur den Inhalt, Label und Rolle des fokusierten Bereichs selbst vorlesen und der Link keinen wirklichen Inhalt hat, ist der Srpung nicht wirklich bemerkbar. Eine Einführung des tabindex-Tags, als Universalantribut, hätte dem hoffentlich noch kommenden Aria Artikel bestimmt nichts weggenommen.

Dieser Artikel beschreibt mehr wie man Webseiten für User mit augeschaltetem JS zugänglich macht, nicht wie man barrierefreies JavaScript schreibt.

Wenn ich demnächst einen Artikel über einen barrierefreien Fahrstuhl schreiben würde, würde ich auch 3/4 meines Artikels ersteinmal darauf verwenden, die Grundlagen einer (barrierearmen) Treppe zu erklären (auch Häuser mit Fahrstühlen müssen ja Treppen haben).

Ich hoffe nur, dass meine Leser dann nicht wirklich glauben der Fahrstuhl, den sie bauen könnten, wäre barrierefrei.

Das gefährliche an diesen vermeintlich barrierefreien JS-Tuorials und Artikeln ist, dass viele Entwickler eben an dieser sehr oberflächlichen Betrachtung von barrierefreiem JS stehen bleiben und nicht über die Ein- und Ausgabe-Unabhängigkeit ihres JavaScripts selbst nachdenken.

Während sich die WCAG 1.0 vor allem auf HTML und CSS beziehen und für fast alle anderen Techniken im Grunde immer eine HTML-Alternative verlangen, akzeptieren die WCAG 2.0 grundsätzlich jede Technologie, die gewissen Mindestanforderungen in Sachen Zugänglichkeit entspricht. Zu diesen akzeptierten Technologien zählt aus Sicht der WCAG 2.0 auch Javascript.

Permanenter Link

Siegfried
am 07.12.2008 - 11:39

Das mit der .js Klasse ist klasse, danke! Damit kann ich vielleicht wieder meinen Javascript Styleswitcher für den IE reaktivieren. Mal sehen.

Ich hatte das mal so gemacht, dass ich die Style Auswahlbox erst per Javascript erzeugt und eingebaut habe. Der Gedanke dahinter: Wenn Javascript nicht aktiv ist, wird der Nutzer auch nicht durch eine nicht funktionierende select Box genervt. Hat in allen Browsern funktioniert, nur nicht im IE. Der hat die Box zwar eingebaut, es aber nicht geschafft, die Javascript event Handler dazu mit zum laufen zu bringen. Also habe ich das wieder rausgeschmissen. Mit der .js Klasse und etwas CSS ließe sich eiwas Ähnliches und funktionierendes auch für den IE anbieten.

Ich habe dann nur noch ein Problem damit, diesmal mit dem Firefox. Bei diesem wird die Styleauswahl persistent durch eine Extension. Diese weiss aber Nix von einer Änderung via Javascript und macht selbige Änderung stante pede wieder rückgängig. Dieses Problem muss ich noch lösen. Aber immerhin hat mich dieser Artikel hier einen Schritt weiter gebracht.

Permanenter Link
Dirk Jesse

Dirk Jesse (Autor)
am 07.12.2008 - 19:31

@Alexander,

vielleicht geht es aus Überschrift und Teaser nicht eindeutig genug hervor, doch dieser Beitrag richtet sich an JS-Einsteiger. jQuery, YUI und andere JS-Frameworks haben die Hemmschwelle für den JS-Einsatz stark verringert.

Natürlich hast Du recht damit, dass diese Regeln noch lange nicht alles sind, aber sie sind die notwendigen Schritte für den Start.

Dieser Artikel beschreibt mehr wie man Webseiten für User mit augeschaltetem JS zugänglich macht, nicht wie man barrierefreies JavaScript schreibt.

Genau das ist ein wichtiger Punkt, der in Verbindung mit der einfachen Anwendung von JS-Frameworks oft vergessen wird. Zwar zwingt die WCAG 2.0 nicht mehr dazu, dass in jedem Fall ein HTML/CSS-Fallback vorhanden sein muss, in den vielen Fällen macht dies jedoch auch weiterhin Sinn.

Der Beitrag soll nicht vermitteln, dass die oben genannten 7 Regeln bereits das Ende der Weisheit sind. Es sind die absoluten Basics und wer sich in das Thema einlesen will, wird ohne Zweifel weitere Literaturquellen bemühen müssen.

Was das gezielte Setzen des Focus betrifft, wird es hoffentlich in Kürze einen Artikel von Dirk Ginader zu einem barrierefreien Tab-Script geben. Für den Adventskalender wurde es leider zu spät fertig. Dirk wird aber sicherlich dazu entweder hier oder in seinem eigenen Blog in Kürze einen Beitrag veröffentlichen.

Permanenter Link

alexander farkas
am 07.12.2008 - 22:23

Hallo Dirk,

ich bin etwas aufbrausend, was das Thema angeht und ich findn Deinen Artikel zu unobtrusiven Javascript wirklich gut. Einige Dinge sind mit kurzen Worten sehr gut erklärt.

Und du hast auch recht, dass das ein wichtiges Thema ist.

Meine Grundkritik bleibt dennoch bestehen - gerade weil es erkennbar ein Einsteigertutorial ist.

Der Artikel vermittelt den Eindruck, dass das Wichtigste an zugänglichem JS schlichtweg die Frage ist, ob die Seite auch ohne JS noch funktioniert. Und diese Halbwahrheit schadet mehr, als dass sie hilft. Das führt in aller Regelmäßigkeit dazu andere schwerwiegende Barrieren nicht zu berücksichtigen.

Dieser Eindruck wird insbesondere dadurch verstärkt, dass das Beispiel einen Teil der Funktionalität ausschließlich bei einem mouse-enter/leave Event zugänglich macht. Angesichts der Tatsache, dass man nicht weiss, welche Funktionalität sich dahinter verbirgt, hätte man es sich leicht machen und dieselben Eventhandler - unter Hinweis der Tastaturbenutzbarkeit - ebenso für focus/blur verwenden können.

Bzgl. Tab-Script bin ich tatsächlich sehr gespannt. Gerade bei dem Tab-Widget weiß ich nicht wie andere zu dem Problem um die Ctrl-PageUp/PageDown - Behandlung stehen. (Bei Jaws wird bei eingeschalteter "Menühilfe" diese Nutzungsmöglichkeit zu allem Überfluß auch noch angesagt.) kurze Beschreibung der Ctrl-PageUp/PageDown-Funktionalität und dem dazugehörigen Problem

Permanenter Link

Die Kommentare sind geschlossen.