Label inside – Beschriftung in Formularfeldern

Autor
Gunnar Bittersmann
Letzte Änderung
2010-04-14

Diese Artikel steht in leicht gekürzter Fassung im VZ-Developer-Blog und kann dort kommentiert werden.

Immer häufiger findet man auf Webseiten Eingabefelder, die „es in sich haben“: Wenn der Nutzer das Feld noch nicht ausgefüllt hat bzw. das Feld nicht vorausgefüllt ist, wird die zugehörige Beschriftung im Eingabefeld selbst angezeigt – zur Unterscheidung von Nutzereingaben meist grau. Dies ist platzsparend und dem Nutzer können zusätzliche Informationen gegeben werden.

Probleme mit @value

Dies wird oft so umgesetzt, dass die Beschriftung in den Wert des @value-Attribut des input-Elements bzw. den Inhalt des textarea-Elements gesetzt wird; die Aus- und Einblendung geschieht per JavaScript. Diese technische Umsetzung ist jedoch problematisch:

Lösung mit label

Markup

Diese Schwierigkeiten umgeht man, wenn man die Beschriftung mit dem dafür vorgesehenen HTML-Element label realisiert. Dieses wird zusammen mit dem Eingabefeld in einem Containerelement der Klasse "labelinside" gekapselt:

<span class="labelinside"> <label for="foo">Label inside</label> <input id="foo"/> </span> <div class="labelinside"> <label for="bar">Label inside</label> <textarea id="bar" cols="42" rows="3"></textarea> </div>

Das @for-Attribut des label-Elements sorgt dafür, dass man mit der Maus im Eingabefeld auch dort klicken kann, wo der Beschriftungstext steht, denn dadurch wird das Eingabefeld mit der entsprechenden ID fokussiert.

Auch vorbelegte Felder sind mit dieser Methode problemlos möglich:

<span class="labelinside"> <label for="baz">Label inside</label> <input id="baz" value="vorbelegt"/> </span> <div class="labelinside"> <label for="quz">Label inside</label> <textarea id="quz" cols="42" rows="3">vorbelegt</textarea> </div>

Stylesheet

Da das Aus- und Einblenden der Beschriftung mit JavaScript efolgt, wird sie per CSS ausgeblendet, damit sie bei deaktiviertem JavaScript nicht dauerhaft sichtbar ist und die Eingabe behindert.

Damit die Beschriftung im Eingabefeld erscheint, wird das label-Element per absoluter Positionierung aus dem Fluss genommen und im Containerelement oben links positioniert. Dazu muss das Containerelement selbst auch positioniert sein:

.labelinside { margin: 3px 0; position: relative; } .labelinside label { color: silver; cursor: text; display: none; font-size: 0.8em; left: 0; line-height: 0.8em; padding: 6px 3px; position: absolute; top: 0; } .labelinside input, .labelinside textarea { margin: 0; }

(Wenn keine @for-Attibute für die label-Elemente verwendet werden, wäre .labelinside input, .labelinside textarea { background-color: transparent; position: relative } anzugeben, damit man auch auf den Beschriftungstext klicken kann. Das zeigt jedoch im Internet Explorer keine Wirkung und ist deshalb nicht zu empfehlen.)

JavaScript

Der Einfachheit wegen wird das jQuery-Framework [jQuery] benutzt. Das jQuery-Framework und das Label-inside-Script werden am Ende des body-Elements eingebunden. [Ginader]

Zuerst werden alle input- und textarea-Elemente selektiert, die Kindelemente eines Containerelements der Klasse "labelinside" sind:

var $inputControl = $(".labelinside>input, .labelinside>textarea");

Beim Seitenaufruf sollen die Beschriftungen aller dieser Eingabefelder eingeblendet werden, die nicht vorausgefüllt sind; die anderen bleiben ausgeblendet. Außerdem wird die display-Eigenschaft von inzeiligen Containerelementen auf "inline-block" geändert, damit die Beschriftung auch bei diesen passt; dies jedoch nicht für Internet Explorer < 8. (Abfrage per conditional compilation [JavaScriptKit] und document.documentMode [Sebestyen])

$inputControl.each(function (index, domElement) { /*@cc_on if (document.documentMode && document.documentMode >= 8) @*/ if ($(this).parent().css("display") == "inline") $(this).parent().css("display", "inline-block"); if (!$(this).val()) $(this).parent().children("label").show(); });

Beim Fokussieren eines Eingabefeldes wird dessen Beschriftung ausgeblendet; beim Verlassen wird dessen Beschriftung eingeblendet, wenn kein Eingabewert im Feld steht:

$inputControl.bind("focus", function(event) { $(this).parent().children("label").hide(); }); $inputControl.bind("blur", function(event) { if (!$(this).val()) $(this).parent().children("label").show(); });

Und so sieht’s aus:

Automatisch fokussiertes Eingabefeld

Der Nutzer sollte auf einer Webseite gleich mit dem Ausfüllen von Eingabefeldern beginnen können, ohne dass dazu eine Aktion notwendig ist, die das erste Eingabefeld fokussiert. HTML5 führt dazu das @autofocus-Attribut ein, das auch schon von einigen Browsern unterstützt wird.

<span class="labelinside"> <label for="autofocus">Label inside</label> <input autofocus="autofocus" id="autofocus"/> </span>

Dieses Eingabefeld (nur eins sollte @autofocus haben) muss nicht im gesamten DOM gesucht werden, sondern in den schon gefundenen Label-inside-Eingabefeldern. (Die Selektion des Eingabefelds wäre auch über dessen ID möglich.)

Für Browser, die @autofocus noch nicht unterstützen, wird der Fokus mit JavaScript gesetzt.

var $autofocus = $inputControl.filter("[autofocus]"); $autofocus.focus();

Für dieses Element ist das Ausblenden der Beschriftung beim Aufruf der Seite nicht ratsam, wenn der Nutzer dadurch keine Information bekommt, was er in dieses Feld eintragen sollte. Deshalb wird die Beschriftung anfangs eingeblendet. Im Internet Explorer ist dabei eine kurze Verzögerung notwendig, die per conditional compilation [JavaScriptKit] eingebunden wird, damit die Ausführung in anderen Browsern nicht verzögert wird.

Die Beschriftung wird ausgeblendet, sobald Text eingegeben wird oder wenn mit der Maus in das Eingabefeld geklickt wird.

if (!$autofocus.val()) /*@cc_on setTimeout(function () { @*/ $autofocus.parent().children("label").show(); /*@cc_on }, 0); @*/ $autofocus.bind("click", function(event) { $(this).parent().children("label").hide(); }); $autofocus.bind("keyup", function(event) { $(this).parent().children("label").hide(); });

Und so sieht’s aus:

Vorteile dieser Lösung

Bei dieser Lösung sind Präsentationsschicht (CSS) und Verhaltensschicht (JavaScript) sauber voneinander getrennt. (Das Umsetzen des Wertes der display-Eigenschaft von "inline" nach "inline-block" nimmt dem Seitenautor die Arbeit ab, den Wert explizit zu setzen.)

Beschriftung und Nutzereingaben sind sauber voneinander getrennt; eine ungewollte Übernahme des Beschriftungstextes als Eingabe kann nicht erfolgen.

Es genügen wenige Codezeilen für alle Eingabefelder auf einer Webseite. Zur Unterscheidung von Beschriftung und Nutzereingaben in den Feldern sind keine Flags oder gar Stringvergleiche des value mit dem (für jedes Eingabefeld anderen) Beschriftungstext erforderlich. Der Stil für den Beschriftungstext steht im Stylesheet; mit JavaScript muss lediglich die Sichtbarkeit geändert werden, nicht jedoch die Textfarbe o.a. Dadurch ist die Lösung nicht nur einfach, sondern auch schnell.

Referenzen

Ginader
Dirk Ginader, Sehr sehr schnelle Seiten – Website Performance Best Practice – Teil 2, Webkrauts-Advendskalender 2008, http://www.webkrauts.de/2008/12/14/sehr-sehr-schnelle-seiten-website-performance-best-practice-teil-2/
JavaScriptKit
Conditional Compilation of JScript/ JavaScript in IE, JavaScript Kit, http://www.javascriptkit.com/javatutors/conditionalcompile.shtml
jQuery
http://jquery.com/
Sebestyen
Thomas J. Sebestyen, Kompatibilitätsmodus im Internet Explorer 8, SELFHTML aktuell Weblog, http://aktuell.de.selfhtml.org/weblog/kompatibilitaetsmodus-im-internet-explorer-8