CSS 2.1 ::Artikel

Online-Formulare - schön und zugänglich

Das Original dieses Textes wurde zuerst am 20. Juni 2006 unter dem Titel Prettier Accessible Forms im Online-Magazin A List Apart veröffentlicht. Der Autor ist Nick Rigby. Die Übersetzung erfolgte mit Genehmigung von A List Apart und dem Autor. Bemerkungen des Autors aus der Kommentarsektion sind im Text ergänzt.
Translated with the permission of A List Apart Magazine and the author. Authors remarks in the comments section are added at the bottom.

Wenn man Formulare so codieren will, dass sie gleichzeitig gut aussehen und die Kriterien der Webzugänglichkeit erfüllen, kann das eine ziemlich zeitraubende Angelegenheit sein. Insbesondere die Elemente label und input nebeneinander zu platzieren, kann zu einem echten Problem werden. Früher haben wir so etwas mit Tabellen gemacht, und das funktionierte in Szenarien wie diesem auch recht gut. Formulare bestehen aber nun mal nicht aus tabellarischen Daten, wir haben also genau genommen mit einem semantischen Lapsus gearbeitet.

Hier habe ich versucht, eine Lösung zu entwerfen, die zugleich zugänglich und projektübergreifend anwendbar ist. Ich löse meine Designprobleme oft mit Floats. Wenn man aber bedenkt, wie komplex Layouts werden können und wie viele Bugs des Internet Explorer mit float zu tun haben, dann sind Lösungen mit float nicht immer einfach auch in anderen Projekten nutzbar. Ich wollte etwas entwickeln, das jeder einfach auf jedes andere Projekt portieren kann. Ich wollte ein Stylesheet, das die Basis des geforderten Layouts bildet, wenn man es an ein korrekt codiertes HTML-Formular anbringt. Hier ist also mein Versuch, ein übertragbares und zugleich zugängliches Webformular zu codieren.

Bild 1: Beispielformulare

Das HTML des Formulars

Der wichtigste Teil jedes Web-Formulars ist der HTML-Code. Glücklicherweise stellt HTML uns ein paar nette Tags zur Verfügung, aus denen wir unser zugängliches Formular zusammensetzen können. Sie heißen fieldset, legend und label. Für alle, die mit diesen Elementen weniger vertraut sind, folgt hier eine kurze Übersicht [Eine ausführlichere Zusammenfassung gibt's bei SelfHTML: Gruppierung von Elementen und Label für Elemente, d. Ü.] :

Die Elemente fieldset und legend

Das Element fieldset gibt uns die Möglichkeit, Formularelemente in verwandte, logische Feldgruppen einzuteilen. Mit legend können wir dann jede Gruppe mit einem ansprechenden Titel versehen, der den Zusammenhang zwischen den einzelnen Feldern leichter verständlich macht. Einige Vorleseprogramme wiederholen diesen Titel vor jeder einzelnen Feldbeschreibung innerhalb der Gruppe. So kann ein bestimmtes Feld auch von Menschen mit Behinderungen immer seiner Gruppe zugeordnet werden.

Das Element label

Mit Hilfe des Elements label können wir jedem input-Feld eine eigene Beschriftung geben. Feld und Beschriftung sind einander bereits auf Code-Ebene zugeordnet.

Ein einfaches Beispiel dazu könnte so aussehen:

<fieldset> <legend>Delivery Details</legend> <ol> <li> <label for="name">Name<em>*</em></label> <input id="name" /> </li> <li> <label for="address1">Address<em>*</em></label> <input id="address1" /> </li> <li> <label for="address2">Address 2</label> <input id="address2" /> </li> <li> <label for="town-city">Town/City</label> <input id="town-city" /> </li> <li> <label for="county">County<em>*</em></label> <input id="county" /> </li> <li> <label for="postcode">Postcode<em>*</em></label> <input id="postcode" /> </li> <li> <fieldset> <legend>Is this address also your invoice address?<em>*</em></legend> <label><input type="radio" name="invoice-address" /> Yes</label> <label><input type="radio" name="invoice-address" /> No</label> </fieldset> </li> </ol> </fieldset>

Das HTML dieses Beispiels ist recht einfach gestrickt, aber Ihnen sind wahrscheinlich schon einige Dinge aufgefallen. Zum einen verwende ich innerhalb der übergeordneten Feldgruppe eine geordnete Liste, aus zwei Gründen:

  1. Ich verwende jeden Listenpunkt li als Container für eine Zeile des Formulars, dadurch wird die Formatierung einfacher.
  2. Aus semantischen Gründen: die Listenelemente geben den einzelnen Feldern eine gewisse logische Ordnung.

Darüber hinaus geben einige Vorleseprogramme am Beginn einer geordneten Liste die Anzahl der Listenpunkte als zusätzliche Information aus.

Felder, die zwei oder mehr Optionen enthalten, z. B. Radiobuttons, sind in einer weiteren, verschachtelten Feldgruppe zusammen gefasst. Dies ergibt eine logische Strukturierung der gegebenen Optionen, in unserem Fall der Radiobuttons, mit dem Element legend als Erklärung dazu. Anschließend ist jede Option noch mit ihrem eigenen Element label versehen. So erzielen wir eine gute Zugänglichkeit und geben den Nutzern, die auf unterstützende Technologien angewiesen sind, eine wirkliche Hilfestellung.

Formatierung des Formulars

Jetzt kommen wir zum besten Teil, dem Erstellen des Stylesheets. Mein Ziel war ein übergeordnetes Stylesheet für Formulare, das importiert werden kann und den Formularen ihre grundlegende Struktur gibt, so wie wir sie brauchen. Hier ist es:

form.cmxform fieldset { margin-bottom: 10px; } form.cmxform legend { padding: 0 2px; font-weight: bold; } form.cmxform label { display: inline-block; line-height: 1.8; vertical-align: top; } form.cmxform fieldset ol { margin: 0; padding: 0; } form.cmxform fieldset li { list-style: none; padding: 5px; margin: 0; } form.cmxform fieldset fieldset { border: none; margin: 3px 0 0; } form.cmxform fieldset fieldset legend { padding: 0 0 5px; font-weight: normal; } form.cmxform fieldset fieldset label { display: block; width: auto; } form.cmxform em { font-weight: bold; font-style: normal; color: #f00; } form.cmxform label { width: 120px; /* Width of labels */ } form.cmxform fieldset fieldset label { margin-left: 123px; /* Width plus 3 (html space) */ }

Wir sehen, das ist alles nicht allzu schwierig, und wer genau hinsieht, wird schon den Wert inline-block der Eigenschaft display bemerkt haben. Für alle, die mit diesem Wert noch nicht vertraut sind, folgt hier die kurze Erklärung aus der Referenz der Eigenschaft display:

Der Wert inline-block bewirkt, dass das Element äußerlich wie eine Inline- Box innerhalb der Textzeile formatiert ist, ähnlich einem replazierten Element. Das Innere einer Inline-Block- Box ist jedoch wie eine Block- Box formatiert. Das Element innerhalb der Box ist wie ein replaziertes Element formatiert.

Das ist schon der ganze Trick, aber wie üblich geht nicht alles so einfach, deshalb kommt jetzt eine gute und eine schlechte Nachricht. Die gute zuerst: Internet Explorer hat kein Problem mit diesem Wert, weder in der Windows-Version noch in der Mac-Version. (Als ergänzende Anmerkung sei gesagt, dass der IE den Wert inline-block nur für Inline- Level- Elemente, aber damit eben auch für label, verarbeitet.) Die schlechte Nachricht betrifft ausnahmsweise einmal die Gecko-basierten Browser: sie unterstützen den Wert inline-block nicht direkt und wir müssen uns etwas einfallen lassen. Das tun wir auch, etwas weiter unten.

Beispiel 1:
enthält einige zentrale CSS-Regeln, die nur minimalen Einfluss auf die Darstellung haben.

Ich wollte ein Stylesheet entwickeln, das die zentralen Formate für Formulare enthält und das ein Teil einer größeren Stylesheet-Bibliothek sein kann. Theoretisch könnten solche Stylesheets ohne Änderungen einfach in eine beliebige Website eingesetzt werden und damit ein grundlegendes Gerüst aus CSS-Regeln liefern. Ich sehe das als ersten Teil meiner Vision einer Stylesheet-Bibliothek, mit der sich die bekannten CSS-Probleme handhaben lassen.

Der größte Vorteil davon ist, dass jeder voreingestellte Wert geändert werden kann, weiter unten in der Kaskade oder durch einen Selektor höherer Spezifizität. Die Anpassung der Formulare an ein bestehendes Site-Design erfolgt dann einfach durch zusätzliche Regeln, die in separaten Stylesheets vorgehalten werden können, wie in unserem schon etwas besser aussehenden Beispiel 2.

Browser-Bugs

Wie oben schon erwähnt, können Mozilla/Firefox-Surfer bis jetzt noch nicht sehen, um was es hier geht, denn dummerweise unterstützt die Gecko-Engine nicht den Wert inline-block. Das ist zwar ein Problem, Mozilla/Firefox kennt aber einen browserspezifischen Wert -moz-inline-box, der sich im Großen und Ganzen wie der Wert inline-block verhält. Nur wenn die Beschriftung im Element label zu lang wird, müssen wir ein klein wenig tricksen. Da der Wert -moz-inline-box einen Zeilenumbruch verhindert, verschwindet das Ende der Beschriftung dann unter dem Textfeld. Wir helfen uns, indem wir innerhalb des mit -moz-inline-box formatierten Elementes ein Block- Element einfügen, das dann den Text der Beschriftung aufnimmt. Für dieses Element geben wir eine Breite an, dadurch werden lange Labels auch im Mozilla/Firefox umgebrochen.

Wenn wir das alles per Hand in unser Dokument einfügen, sieht unser bisher schön und schlank gehaltener Quellcode ein wenig unordentlich aus. Und was soll mit all dem eingefügten HTML passieren, wenn wir unser Layout später einmal ändern? Aber auch dafür gibt es eine Lösung: JavaScript und DOM.

Normalerweise bin ich der Meinung, dass JavaScript nicht zur Formatierung verwendet werden sollte. Diese Regel hab ich hier nur deshalb gebrochen, um die Unzulänglichkeit eines Browsers (die zur Zeit leider noch existiert) auf unauffällige Weise zu überspielen. Es wird an zwei Stellen Code eingefügt, den wir sonst manuell einfügen müssten und bei Änderung des Layouts manuell auch wieder entfernen müssten. Die Funktionsweise der Formulare wird durch das JavaScript nicht beeinträchtigt und die gesamte Methode bietet nach meiner Erfahrung eine robuste Lösung für ein bekanntes Problem.
(Das Zeichen steht für vom Editor eingefügte Zeilenumbrüche):

if( document.addEventListener ) document.addEventListener( 'DOMContentLoaded', cmxform, false); function cmxform(){ // Formulare verstecken $( 'form.cmxform' ).hide().end(); // Berechnung $( 'form.cmxform' ).find( 'li/label' ).not( '.nocmx' ) .each( function( i ){ var labelContent = this.innerHTML; var labelWidth = document.defaultView. getComputedStyle( this, '' ).getPropertyValue( 'width' ); var labelSpan = document.createElement( 'span' ); labelSpan.style.display = 'block'; labelSpan.style.width = labelWidth; labelSpan.innerHTML = labelContent; this.style.display = '-moz-inline-box'; this.innerHTML = ""; this.appendChild( labelSpan ); } ).end(); // Formulare ausgeben $( 'form.cmxform' ).show().end(); }

Um die Verarbeitung zu vereinfachen, verwendet unser JavaScript die hervorragende JavaScript- Bibliothek JQuery, die wir dazu auch mit einbinden müssen. Hier folgt eine kurze Beschreibung der Funktionsweise:

Zuerst verstecken wir alle Formulare, die die Klasse cmxform aufweisen.

// Formulare verstecken $( 'form.cmxform' ).hide().end();

Es sieht ein wenig merkwürdig aus, wenn die Teile des Formulars beim Aufbau der Seite hin- und her gerückt werden. Deshalb verhindern wir die Darstellung des Formulars, bis es komplett aufgebaut ist und geben es dann erst frei.

Die nächste Anweisung soll nur für alle Elemente label gelten, wenn sie direkte Nachkommen eines Elements li sind und nicht die Klasse nocmx aufweisen. Wir filtern sie mit Hilfe unserer JQuery-Methoden und einer Kombination aus CSS-Selektoren und XPath.

$( 'form.cmxform' ).find( 'li/label' ).not( '.nocmx' ) .each( function( i ){ ...

Den nocmx-Filter verwende ich deshalb, weil andere Autoren dann diese Klasse für die Labels verwenden können, die sie anders gestalten wollen. Ich nutze diese Technik schon eine Weile und hab dabei entdeckt, dass diese Möglichkeit durchaus nützlich sein kann. Für jedes ausgefilterte Label wird anschließend noch ein Element span eingefügt und damit auch das Problem des Wertes inline-block aus der Welt geschafft.

$( 'form.cmxform' ).find( 'li/label' ).not( '.nocmx' ) .each( function( i ){ ... }

Schließlich holen wir unsere Formulare wieder hervor und alles sieht genauso aus, wie wir uns das gedacht haben.

// Formulare ausgeben $( 'form.cmxform' ).show().end();

Noch ein Nachtrag zum Aufruf des Scripts: ich verwende die Mozilla-spezifische Methode document.addEventListener() . Das bedingt, dass das Script nur im Mozilla/Firefox läuft (woanders brauchen wir es ja auch nicht) und dass es startet, sobald das DOM geladen ist.

Auch wenn JavaScript vielen nicht als die eleganteste Lösung erscheint, bleibt es doch hier sehr unauffällig und bei Nutzern, die JavaScript nicht freigegeben haben, fällt das Formular problemlos auf eine einfachere Form zurück.

Auch für Internet Explorer müssen noch einige Kleinigkeiten zurechtgebogen werden. Im IE/Win ist die Position der Legenden noch nicht optimal. Durch ein paar negative Werte für margin rechts oder links erreichen wir, dass sie sich sauber in einer Flucht aufreihen.

form.cmxform legend { padding: 0 2px; font-weight: bold; _margin: 0 -7px; /* IE Win */ }

Für IE/Mac 5 brauchen wir ebenfalls noch einen kleinen Hack, um einen seltenen Ausgabefehler zu beheben:

/*\*//*/ form.cmxform legend { display: inline-block; } /* IE Mac legend fix */

Mit diesem Hack können wir Regeln speziell für IE/Mac 5 einführen. Wenn Sie browserspezifische Regeln lieber nicht durch CSS-Hacks einfügen, ist das auch kein Problem.

Ich hab diese Hacks hier eingefügt, weil ich die Technik so portierbar wie möglich halten wollte. Wenn Sie sowieso browserspezifische Stylesheets vorhalten, können Sie diese Regeln auch nach dorthin verlagern.

Der letzte Schliff

Fertig! Jetzt brauchen wir nur noch die passenden cmxform-Dateien anzubinden und die Klasse cmxform in den Formularen einzufügen. Viel Vergnügen.

Diese Formulartechnik ist in folgenden Browsern getestet:
Safari 2.0.3,
Firefox 1.5, Netscape 7.2 (Mac), and Netscape 8.1 (Win)
Opera 8.5,
Internet Explorer 7b2 , Internet Explorer 6, Internet Explorer 5 (Win), Internet Explorer 5.2 (Mac).

Nachtrag

In der Diskussion über diesen Artikel weist der Autor auf ein Problem mit Opera 9 hin. Auch wenn das JavaScript nicht für Opera vorgesehen ist, gibt es damit keine Probleme, wenn man eine Zeile des Scripts austauscht. Für:

this.innerHTML = null;

setzt man diese Zeile ein:

this.innerHTML = ””;

Die Änderung ist in dieser Übersetzung bereits eingearbeitet.

Einige Leser schlagen vor, anstelle des Ausdrucks

if( document.addEventListener )

die Browserkennung aus jquery zu nutzen:

if($.browser.mozilla)

Dadurch wird Opera automatisch ausgeschlossen und es können keine Probleme mehr auftreten.

Insgesamt weist der Autor aber darauf hin, dass JavaScript hier nur zur Lösung eines durchaus temporären Problems eingesetzt wird, das nach dem nächsten CSS-Update sowieso gelöst ist.
TOP
Author: Nick Rigby
Translation: kl

Hinweis:
Das Original dieses Textes wurde zuerst am 20. Juni 2006 unter dem Titel Prettier Accessible Forms im Online-Magazin A List Apart veröffentlicht. Der Autor ist Nick Rigby. Die Übersetzung erfolgte mit Genehmigung von A List Apart und dem Autor.
Translated with the permission of A List Apart Magazine and the author.


Home|Vollreferenz|Schnellreferenz|Grundlegendes|Tutorials & Artikel|Quiz|Allgemeines

© Copyright All Contents 2002-2023
Commercial Use prohibited.


Notizen: