Wer zum ersten Mal mit CSS in Berührung kommt, findet das Box Model meist etwas unintuitiv. Wenn man da nämlich einem Element eine Breite oder Höhe gibt und es zusätzlich mit einem Rahmen oder einem Innenabstand versieht, plötzlich breiter und höher als angegeben – denn die Breitenangabe gilt nur für den Inhalt der Elements, nicht für das Element selbst. Manchmal ist dieses Verhalten auch für Nicht-Anfänger etwas unpraktisch. Mit der CSS3-Eigenschaft box-sizing könnte das Problem bald gegessen sein, denn das ist nicht weniger als ein Opt-Out für ein Box Model wie wir es kennen.
Was macht box-sizing?
Mit box-sizing kann man für seine Elemente ein alternatives Boxmodel aktivieren. Normalerweise sähe ein Block-Element mit einer fest definierten Breite, einer Border und etwas Padding so aus:
Die Angabe der Breite (oder auch einer Höhe) betrifft also den Inhalt eines Elements, während das Element selbst durch Borders oder Padding noch höher oder breiter werden kann. Dieses Verhalten kann unter bestimmten Umständen durchaus einige Dinge verkomplizieren, wenn man beispielsweise mit kombinierbaren CSS-Klassen arbeitet.
Kombiniert man man die Klasse standardbox mit border-alpha, hat das Endprodukt andere Maße als wenn man border-beta benutzt. Und das kann bei einem Layout mit vielen gefloateten Boxen schnell mal unangenehme Auswirkungen haben. Und genau hier hilft box-sizing. Das oben abgebildete Beispiel sähe mit box-sizing:border-box; so aus:
Also: Mit box-sizing:border-box; legen height und width nicht mehr die Maße des Inhalts eines Elements, sondern die Maße des Elements selbst fest und berücksichtigt dabei Rahmen und Abstände.
Wie benutzt man box-sizing?
Diese Frage ist etwas komplizierter als man meinen möchte. Wie man box-sizing benutzt hängt tatsächlich davon ab, welches CSS-Modul man fragt. Im Moment ist CSS3 ja noch in der Entwicklung und da kommen solche Diskrepanzen zwischen den einzelnen Modulen schon mal vor. Das CSS3 Basic User Interface Module sieht für box-sizingfolgende Werte vor:
content-box: Altes/Normales Box Model
border-box: Neues Box Model, Rahmen und Innenabstände verbreitern ein Element nicht mehr
inherit: Vom Elternelement übernehmen (Standardwert)
Beim CSS Advanced Layout Module geht man von folgenden Werten aus:
content-box: Altes/Normales Box Model (Standardwert)
padding-box: Neues Box Model, Innenabstände verbreitern ein Element nicht mehr
border-box: Neues Box Model, Rahmen verbreitern ein Element nicht mehr
margin-box: Neues Box Model, zusätzliche Außenabstände verkleinern ein Element, so dass seine Breite mit Margin zusammen nicht die vorgegebene Breite überaschreitet
Wie wir wissen kann etwas nur W3C-Standard werden, wenn mindestens zwei unterschiedliche Implementierungen in den gängigen Browsern vorliegen. Und so gesehen spricht einiges dafür, dass die erste Variante Realität wird – denn die findet man bereits in allen Browserfamilien.
Welche Browser unterstützen box-sizing?
Opera kennt box-sizing und Mozilla, Webkit-Browser sowie der IE8 nehmen es mit ihren jeweiligen Prefixen (-moz, -webkit und -ms, also z.B. -moz-box-sizing) an. Dabei handelt es sich jeweils um die Variante aus dem CSS3 Basic User Interface Module mit den möglichen Werten content-box, border-box und inherit. Der Firefox hat zusätzlich noch den padding-box-Modus aus dem Advanced Layout Module implementiert. Für all das gibt es eine Testseite.
Es sieht also wirklich so aus, also könnten wir in absehbarer Zeit dieses nette CSS3-Feature produktiv einsetzen. Die Welt wird dadurch keine andere, aber vielleicht macht box-sizing das eine oder andere etwas einfacher, zumindest den Einstieg in CSS. Webkit, Mozilla und Microsoft müssen nur noch ihre schon vorhandenen Implementierungen fertigstellen.
Die Internet Explorer 6 und 7 müssten natürlich auch noch aussterben – wobei man diesen Versionen theoretisch mittels dieses Scriptsbox-sizing-Fähigkeiten verpassen könnte. Aber wenn man schon CSS3-Features mit Javascript faken muss, dann vielleicht lieber nur Eyecandy und keine elementaren Layout-Eigenschaften.
In den letzten Tagen wurde vielerorts fleißig zu Thema Einsatz von HTML5 im Jahr 2009 debattiert und geforscht. Ich möchte die Ergebnisse davon mit meinen eigenen Erfahrungen in diesem Artikel zusammenfassen und mit etwas Kommentierung und Beispielen garnieren. Ich darf schon mal vorwegnehmen, dass ich durchaus gedenke, in Zukunft für meine Arbeit HTML5 überall dort zum Standard zu erheben, wo bislang XHTML Strict im Einsatz war. Wie weit dieser Einsatz dann genau geht, hängt von den Details ab. Und um die geht es im Folgenden.
Der Doctype
Der Doctype von HTML5 ist durch die Tatsache, dass man ihn sich merken kann, schon für sich genommen genug Grund, ab heute nur noch HTML5 zu schreiben:
<!DOCTYPE html>
Da HTML5 in weiten Teilen abwärtskompatibel ist, ist jedes valide XHTML-Dokument auch ein gültiges HTML5-Dokument – man muss nur den Doctype austauschen und minimal aufräumen (z.B. alle acronym rauswerfen – siehe auch HTML 5 differences from HTML 4/Absent Elements). Der neue Doctype hat auch keine negativen Folgen auf das Handling der Dokumente durch heutige Browser. Wie John Resig sagt:
This DOCTYPE is able to push Firefox, Safari, Opera, IE6, IE7, and IE8 into standards mode and allow us to (as best as we can) develop web applications in a standards-based way (CSS, HTML, JavaScript, DOM).
Insofern steht dem Einsatz von HTML5 so oder nichts im Wege. Richtig interessant wird HTML5 natürlich erst, wenn man einen Blick auf die neuen Elemente und Attribute wirft …
Neue Attribute
Ob und wie man die neuen Attribute und Elemente von HTML5 zu irgendwas gebrauchen kann, ist davon abhängig, wie Browser mit ihnen verfahren. Weil die Browser die meisten HTML5-Neuerungen nicht kennen, ist wichtig, wie sie eben mit unbekannten Attributen und Elementen umgehen – für den Durchschnittsbrowser von heute besteht zwischen <section> und <ziryyyyrt> kein Unterschied.
Bei den Attributen ist das noch recht einfach: Alle wichtigen Browser verschlucken unbekannte Attribute einfach und klaglos. Das ist recht praktisch, denn so kann man einem input ohne Bedenken autocomplete="off" oder ein ähnliches neuartiges Attribut verpassen. Kann der Browser damit nichts anfangen, passiert nichts, kennt der Browser das Attribut und verarbeitet es korrekt, gibt es erst recht kein Problem (Testseite).
Neue Elemente
Die neuen HTML5-Elemente kann man in zwei Gruppen einteilen. Einmal gibt es jene, die Browserseitig gewisse Funktionen haben. Das bekannteste Beispiel ist vielleicht <canvas>. Hier gilt natürlich, das alles, was nicht im Browser implementiert ist, nicht funktioniert und entsprechend nicht bedenkenlos in für die Allgemeinheit bestimmten Websites benutzt werden kann.
Einen Sonderfall hierbei bilden die neuen Input-Elemente. In IE6-8, Firefox, Opera und Safari führt ein dem Browser unbekanntes type-Attribut (z.B. date) dazu, dass das Feld zu einem normalen Text-Input wird. Dieses sinnvolle Fallback-Verhalten ermöglicht also die Nutzung der neuen Input-Typen. Auf der Testseite kann man z.B. sehen, dass Opera 9 die Typen date und number unterstützt und dafür spezielle Input-Controls bereitstellt – z.B. für date den Zeitpicker. Mit type="color" kann allerdings auch Opera nichts anfangen und gibt ein normales Textfeld aus. Aber das kann man dann ja trotzdem verwenden.
Und dann gibt es jene Elemente, die man am ehesten als DIV mit ’ner Bedeutung beschreiben könnte. Das sind Dinge wie section, article und header, die wirklich nur zur Strukturierung dienen und keine eingebauten Sonderfunktionen haben bzw. beim Browser voraussetzen. Alles was man normalerweise mit diesen Elementen machen möchte, ist sie mit CSS stylen.
Wenn ein Browser diese Elemente nicht kennt und mit diesen unbekannten Elementen einigermaßen sinnvoll verfährt, interpretiert er sie wie span oder div – als 0815-Elemente, eben ohne besondere Funktion. Und die könnte man sich dann ja bequem so zurechtstylen wie man es gern hätte.
Ja …wenn!
Die Browser-Situation
Die meisten Browser verfahren wie oben beschrieben. Alle rein strukturierenden Elemente kann man völlig bedenkenlos für die neueren Opera- Safari- und Firefox-Versionen einplanen. Unter den noch nicht ausgestorbenen Browsern macht allein der Firefox 2 Probleme – wobei das Aussterben dieser Version ja durchaus abzusehen ist – und natürlich ist dann da noch der Internet Explorer.
Unser Lieblingsbrowser aus Redmond verfährt mit den neuen Elementen natürlich nichteinigermaßen sinnvoll (es wäre wohl sonst auch zu einfach). Alle Versionen von 6 bis 8 produzieren aus folgendem HTML …
Der IE erkennt also nicht <section> und </section> als offnenden und schließenden Tag eines Elements, sondern hält beide für jeweils eigene Elemente, denen jeweils ein schließender Tag verpasst wird. So entsteht <//section> als schließender Tag für </section>.
Da man so etwas nicht stylen oder sonstwie gebrauchen kann, ist das natürlich ungünstig. Aber zum Glück gibt es Workarounds, die dieses Problem nicht aus der Welt schaffen, aber in einigen wenigen Fällen dämpfen können.
Drei Möglichkeiten, HTML5-Elemente im IE zu stylen: Overhead in Kauf nehmen
Die einfachste Möglichkeit ist es, Dokumente lediglich mit HTML5 semantisch zu würzen. Denkbar wäre eine Konstruktion wie diese:
Sollte man sich eines Tages uneingeschränktem HTML5-Support gegenübersehen, kann man das dann überflüssige div rauswerfen und muss dann in seinem Stylesheet nur ein paar #-Zeichen entfernen. Schon hat man immer immer noch perfekt valides, aber dann auch redundanzfreies HTML5.
Das ist streng genommen Overhead mit im Moment vielleicht noch eher zweifelhaftem Nutzen. Andererseits, ist dieses eine nav-Element (bzw. das Div) wirklich so schlimm? Hängt vermutlich vom Einzelfall ab. Bei innerhalb eines Dokuments vielleicht etwas häufiger auftauchenden Elementen wie z.B. section kann man sich schon eher überlegen, auf ständige Div-Redundanz zu verzichten. Aber Prinzip kann man das so machen.
Drei Möglichkeiten, HTML5-Elemente im IE zu stylen: Mit Javascript anmelden
Diese Möglichkeit hatten wir schon mal besprochen: Man kann mit einer Zeile Javascript jedes beliebige Element beim Internet Explorer anmelden. Wenn man zum Beispiel das section-Element zum Einsatz bringen möchte, geht das so:
document.createElement('section');
Die angemeldeten Elemente werden dann so behandelt, wie unbekannte Elemente in anderen Browsern, d.h. man kann mit ihnen in allen Belangen problemlos arbeiten (siehe Testseite). Wer alle HTML5-Elemente auf diese Weise aktivieren möchte, kann auf das HTML5 enabling script zurückgreifen.
Der Haken an dieser Methode ist offensichtlich: Ist Javascript aus, sind die betroffenen Elemente unbrauchbar. In gewissen Szenarien ist die createElement-Funktion sicher hilfreich, aber eine echte Dauerlösung sieht anders aus.
Drei Möglichkeiten, HTML5-Elemente im IE zu stylen: Universal Selector Styling
Im DOM des Internet Explorer stehen nie andere Elemente in unbekannten Elementen, weil bei diesen Start- und Endtag jeweils als eigene Elemente interpretiert werden. Das heißt, dass im IE eine CSS-Regel wie diese nicht funktionieren kann:
Da mag zunächst auf die Idee kommen, dass die Regel mit einem wie folgt modifizierten CSS-Selektor funktionieren sollte:
section + p {
color:red;
}
Aber weil der IE section eben nicht kennt, klappt das eben nicht. Das heißt, dass man dem Namen des Elements aus dem Weg gehen muss, indem man es zum Beispiel mit dem *-Selektor anspricht. Funktionieren würde also das hier:
body > * + p {
color:red;
}
Noch ein etwas komplexeres Beispiel von dieser Testseite. Aus diesem HTML …
<h1>HTML5 - Universal Selector Styling</h1>
<section class="alpha">
<header>
<p>
Ich bin blau
</p>
</header>
<p>
Ich bin rot!
</p>
</section>
<p>
Ich hab keine besondere Farbe
</p>
… wird im IE erwartungsgemäß folgendes DOM:
<h1>HTML5 - Universal Selector Styling</h1>
<section class="alpha"></section>
<header></header>
<p>
Ich bin blau
</p>
</header><//header>
<p>
Ich bin rot!
</p>
</section><//section>
<p>
Ich hab keine besondere Farbe
</p>
Um die beiden p-Elemente mit CSS zu erfassen muss man Selektoren wie die folgenden konstruieren:
Was neben dem *-Selektor auch funktioniert, sind Klassen-Selektoren wie .alpha oder ID-Selektoren wie #alpha. Nur den Namen des Elements muss man immer aus dem Spiel lassen; section.alpha funktioniert nicht.
Das ist nun nicht gerade eine universelle Lösung, denn wie der CSS-Experte weiß: Im IE6 funktioniert der +-Combinator nicht. Aber überall sonst schon. Man kann die unbekannten Elemente selbst nicht stylen und auch die Elemente in unbekannten Elementen nicht direkt. Aber manchmal kann man sich mit dieser Methode etwas zurechttricksen.
Was in HTML5 auch recht nett ist, ist das Konstruktionen wie die folgende erlaubt sind:
<h1>HTML5 - Links um Blockelemente</h1>
<a href="http://www.foo.bar">
<h2>In HTML4 und XHTML1 ist das hier verboten</h2>
<p>
In HTML5 ist es erlaubt. Juhuuu!
</p>
</a>
Wie man auf dieser Testseite feststellen kann, funktioniert das auch weitgehend, Version 6 des Internet Explorer ausgenommen (da streikt der hover-Status). In einigen anderen Browsern scheint der Verlust des active-Status nicht immer korrekt zu funktionieren – wenn das nicht stört, steht der Verwendung von Blockelemente umschließenden Links nicht weiter im Wege.
Das Fazit: Was geht?
An sich spricht nichts gegen den Einsatz von HTML5 in Websites von heute. Man muss nur sehen, wie viel HTML5 man einsetzt. Der einfache Doctype ist zum Beispiel ein echter Bonus ohne Haken. Was man also auf jeden Fall machen kann, ist normales, valides XHTML schreiben und <!DOCTYPE html> darüber setzen.
Zweitens kann man einige HTML5-Elemente direkt verwenden, wenn man ohne den IE6 plant sogar recht viele. Zum Beispiel ist beim Einsatz von time völlig egal, was zurückgebliebene Browser damit anstellen – vorausgesetzt, man möchte dem Element nicht mit CSS zu Leibe rücken, sondern nur mit ihm etwas auszeichen. Mit time eben zum Beispiel eine Zeitangabe. HTML5 belebt außerdem die Elemente <b> und <i> wieder, die eigentlich nie so richtig verschwunden waren und deswegen problemlos verwendet werden können.
Auch die neuen Inputs können so verwendet werden. Wenn ein Browser für ein <input type="date"> eine Zeitpicker-Funktion zur Verfügung stellt ist das nett, aber wenn der Browser als Fallback für unbekannte Input-Typen type="text" verwendet (wie das bei allen relevanten Browsern der Fall ist), geht das auch.
Also, worauf warten wir noch? Auf das endgültige Ende des IE6 vielleicht, aber dazu kommt demnächst auch noch ein Artikel an dieser Stelle.
Wenn man heutzutage HTML5-Elemente benutzt, regieren die meisten aktuellen Browser darauf einigermaßen vernünftig und erlauben zum Beispiel das Styling dieser Elemente ohne viel Ärger. Der Internet Explorer hingegen fällt (erwartungsgemäß) angesichts von wundersamen Dingen wie z.B. <section> von Glauben ab und produziert aus diesem HTML …
Kein Wunder dass man sowas nicht stylen kann. Dieses Problem lässt sich aber reparieren! Es ist sogar recht einfach, man muss das neue Element nur mit einer Zeile Javascript beim IE anmelden:
document.createElement('section');
Schon gibt es keine Probleme mehr (siehe Testseite). Diese Prozedur kann man mit jedem HTML5-Element durchführen das man braucht, oder direkt zum HTML5 enabling script greifen, das das komplette Programm an HTML5-Elementen für den Internet Explorer aktiviert. Klingt für mich etwas nach Overkill, aber wenn man wirklich viele der neuen Elemente einsetzen möchte … warum nicht?
Diese Methode überzeugt. Statt dass man mit Conditional Comments zusätzliche komplettte CSS-Dateien für den IE einbindet, vergibt man je nach IE-Version eine eigene Body-ID. Dann kann man alle Korrekturen in seinen Hauptstylesheet schreiben und spart sich das Gewurste mit Dateien wie ie6.css, ie7.css und wie sie alle heißen mögen. Außerdem entfallen an dieser Stelle beim Seitenaufruf mit dem Internet Explorer gleich ein paar Requests. Eine rundum feine Technik.