protofunc()

Meinung zu HTML5: Semantik noch Flop, progressive enhancement Top

Tags: HTML 5, deutsch, javascript

Ich bin ein großer Freund von HTML5. Allerdings kann ich nicht nachvollziehen, in welcher Form einige – bereits heute – HTML5 nutzen wollen bzw. zu nutzen empfehlen. Die tollen HTML5-Elemente (nav, aside, header, footer..), die wir mit dreckigen Tricks nutzen könnten, bringen nichts. Kein Browser, kein Screenreader und auch keine ernstzunehmende Suchmaschine unterstützen die Semantik der neuen Tags, gleichzeitig bereiten Sie in allen Versionen des Internet Explorer sowie im Firefox 2 erhebliche Probleme und machen einiges kaputt.

Auf der anderen Seite gibt es die schönen WAI-Aria-Landmarks. Sie sind für eine zusätzliche Semantik definitiv der bessere Weg, weil sie im Gegensatz zu den oben genannten HTML 5 Element einfach funktionieren, helfen und nichts kaputt machen.

Andere Elemente wie figure und legend können teilweise durch aria-labelledby/aria-describedby substituiert werden.

Dies ist kein Widerspruch zu HTML 5. Im Gegenteil der HTML 5 Validator validiert inzwischen nicht nur Teile von Wai-Aria, sondern eben auch die Aria-Landmarks.

Neben den problemlos verwendbaren Aria-Attributen, gibt es in HTML5 viele schöne neue Sachen zu entdecken.

  • Man kann sich endlich den doctype merken.
  • Das canvas-Element wird von allen modernen Browsern unterstützt und kann mit excanvas auch im Internet Explorer zum Laufen gebracht werden (allerdings mit deutlich geringerer Performance).
  • Attribute wie autocomplete sind endlich Bestandteil von HTML 5. Ohne dieses Attribut sind mit Javascript erstellte Auto-Suggest-Listen für Eingabefelder unmöglich.
  • Es gibt neue, befreiende Verschachtelungsregeln.
  • Best practices wie beispielsweise document.documentElement.className += ‘js-on’; erzeugen endlich validen Code.

Vor allem jedoch bietet HTML 5 – insbesondere bei Formularelementen – semantische Extras, die Javascript-Entwickler, gleichgültig von der derzeitigen Unterstützung im Browser, dringend benötigen, um eleganten, unobtrusiven Code schreiben zu können.

Wie zusätzliche semantische HTML5-Attribute beim Aufbau von Javascript helfen

Man stelle sich vor, man möchte einen Slider mit numerischen Werten realisieren. Dieser Slider soll jeweils einen vom Backend vorgegeben Startwert, Mindestwert und Höchstwert kennen. Als Javascript-Fallback soll ein einfaches Texteingabefeld dienen.

Während HTML 4 sowie XHTML 1.0 lediglich ein Attribut für den Startwert bieten, hilft uns HTML 5 ebenso beim Mindest- und Höchstwert unseres unobtrusiv zu erstellenden Sliders.

<input type=“number“ value=“3“ min=“1“ max=“10“ />
<!-- oder in Schritten -->
<input type=“number“ value=“3“ min=“1“ max=“10“ step="1" />
<!-- oder gleich als 'slider' -->
<input type=“range“ value=“3“ min=“1“ max=“10“ />

HTML 5 und progressive enhacement

HTML 5 bietet einige interessante Features, welche bereits heute mit Hilfe von Javascript implementiert werden können.

Das oben beschriebene canvas-Element ist ein Beispiel hierfür, ein weiteres sind die zahlreichen Erweiterungen für Formularelemente, welche in Teilen bereits von Browsern implementiert wurden.

Die HTML 5 – Attribute liefern hierbei die semantische Grundlage für die Aktivierung und Konfiguierung des Javascripts.

Vor der Implementierung mit Javascript sollte man grundsätzlich testen, ob das Feature nicht bereits Teil des Browsers ist. Da die neuen HTML-Attribute in der Regel mit einem DOM-Interface korrelieren, ist dieser Test kinderleicht. Hier einige Beispiele mit jQuery:

(function($){

	var form = $('<form><fieldset><textarea /></fieldset></form>');

	$.extend($.support, {
		//wird die Constrain Validation unterstützt?
		checkValidity: !!(form[0].checkValidity),
		// wird das maxlength-Attribut am textarea-Element unterstützt?
		textareaMaxlength: !!( $('textarea', form)[0].maxLength !== undefined || $('textarea', form)[0].maxlength !== undefined)
	});

})(jQuery);

Eine Beispielimplementierung für das placeholder-Attribut

Das placeholder-Attribut bietet ein Formularfeature, welches Frontend-Entwickler tagtäglich bereits heute mit Javascript in Webseiten nutzen; nämlich das Entfernen von vorbelegten Werten in Eingabefeldern. Hierbei ist das Standardverhalten wie folgt definiert: Der Placeholder stellt einen kurzen Hinweistext dar, welcher dem User als vorläufiger Wert im Eingabefeld angezeigt wird, solange das Feld keinen Wert hat und nicht fokusiert ist. Das placeholder-Attribut ist kein Ersatz für ein assoziertes label-Element!

<label for="birthday">Ihr Geburtstag</label>
<input type="text" placeholder="TT.MM.JJJJ" name="birthday" id="birthday" />

In HTML4/XHTML 1 ist die Unterscheidung ob das Eingabefeld einen Wert, welcher sich wie ein Placeholder verhalten soll oder nicht, nicht gelöst. Die derzeit eleganteste Javascript-Technik verwendet hierzu einen Vergleich zwischen der value- und der defaultValue-Eigenschaft. Diese Form der Implementierung kommt jedoch an Ihre Grenzen, wenn der User beispielsweise ein Suchformular absendet und der Suchbegriff aus Usability-Gründen wiederholt wird, um es dem User zu gestatten, ohne Neueingabe den Suchbegriff zu erweitern, verkürzen oder sonst wie zu modifizieren. Da in diesem Beispiel ausnahmsweise der defaultValue nicht die Aufgabe eines Placeholders besitzt, fehlt dem Javascript die entscheidende Information sich korrekt zu verhalten. Dieses Problem kann letztlich nur durch Hinzufügen dieser Extrainformation gelöst werden. Und die Standardisierung dieser Extrainformation stellt gerade eben das placeholder-Attribut dar.

Wie könnte nun eine placeholder-Implementierung aussehen?

Als erstes erweitern wir unseren oben genannten HTML5-Implementierungstest:

var form = $('<form><fieldset><input type=“text“ /><textarea /></fieldset></form>');

$.extend($.support, {
	checkValidity: !!(form[0].checkValidity),
	textareaMaxlength: !!( $('textarea', form)[0].maxLength !== undefined || $('textarea', form)[0].maxlength !== undefined),
	placeHolder: !!($('input', form)[0].placeholder !== undefined || $('input', form)[0].placeHolder !== undefined)
});

Wird das placeholder-Attribut nicht unterstützt, kann mit der Implementierung durch Javascript fortgefahren werden, was wie folgt aussehen könnte.

if(!$.support.placeHolder){

	function resetInput(){
		if(this.value == this.getAttribute('placeholder')){
			this.value = '';
		}
	}

	function fillInput(){
		if(!this.value){
			this.value = this.getAttribute('placeholder');
		}
	}
	$(function(){
		$('input[placeholder]')
			.each(function(){
				var placeHolder = this.getAttribute('placeholder').replace(/\n|\r|\f|\t/g, '');
				this.setAttribute('placeholder', placeHolder);
				if(!this.value){
					this.value = placeHolder;
				}

			})
			.bind('blur', fillInput)
			.bind('focus', resetInput)
		;
	});
}

Das schöne, das Script kann bereits heute für ein besseres placeholder/input-rest-Script eingesetzt werden. (Ich kenne keines mit einem besseren Verhalten). Bei Browsern (zum Beispiel Safari 4), welche dieses Attribut bereits unterstützen, funktioniert das ganze dann auch ohne Javascript. Die Benutzung ist sehr einfach. Konfiguration und Start des Scripts geschehen komplett automatisch.

<label for="birthday">Ihr Geburtstag</label>
<input type="text" id="birthday" placeholder="TT.MM.JJJJ" name="birthday" />

Hier das gesamte Script (Eine verbesserte Variante des Placeholder-Scripts):

(function($){

var form = $('<form><fieldset><input type=“text“ /><textarea /></fieldset></form>');

$.extend($.support, {
	checkValidity: !!(form[0].checkValidity),
	textareaMaxlength: !!( $('textarea', form)[0].maxLength !== undefined || $('textarea', form)[0].maxlength !== undefined),
	placeHolder: !!($('input', form)[0].placeholder !== undefined || $('input', form)[0].placeHolder !== undefined)
});

if(!$.support.placeHolder){
	$(function(){
		$('input[placeholder]')
			.each(function(){
				var placeHolder = this.getAttribute('placeholder').replace(/\n|\r|\f|\t/g, '');
				this.setAttribute('placeholder', placeHolder);
				if(!this.value){
					this.value = placeHolder;
				}

			})
			.bind('blur', function fillInput(){
				if(!this.value){
					this.value = this.getAttribute('placeholder');
				}
			})
			.bind('focus', function resetInput(){
				if(this.value == this.getAttribute('placeholder')){
					this.value = '';
				}
			})
		;
	});
}
})(jQuery);

Fazit

HTML 5 hat deutlich mehr zu bieten als nicht funktionierende HTML-Elemente. Diese sind oftmals nicht mehr als semantischer „Zuckerguß“. HTML 5 kann jetzt schon vielmehr: Es ermöglicht wirklich elegantes und unobtrusives Javascript.

Written August 16, 2009 by
protofunc