Navigation überspringen

Der CSS-Box-Model-Bug

Problem:
Die verschiedenen Browser stellen Elemente unterschiedlich groß dar, wenn ihnen per CSS Werte für Breite (width), Höhe (height), Innenanbstand (padding) und Rahmen (border-width) zugewiesen werden.
Unterschiede durch DOCTYPE-Switch in:
Opera 7.0 bis 8.54, Internet Explorer für Windows
Ursache:

Die Dimensionierung von Elementen wird durch das Box-Modell der CSS 2-Spezifikation eindeutig festgelegt. Die Dimensionen des Inhaltes werden durch die Werte der Eigenschaften width und height bestimmt. Zu diesen Werten werden die Werte von padding und border-width dazugerechnet, um die Größe eines Elementes zu berechnen. Die folgenden Abbildung zeigt diesen Zusammenhang anhand der Breite eines Elementes:

Abbildung: Darstellung des Box-Modells nach CSS 2-Spezifikation

Der Internet Explorer für Windows bis Version 5.5 und in Version 6 im Quirks Mode hat eine etwas andere Vorstellung vom Box-Modell. Hier werden die Werte für padding und border von den Werten von width und height abgezogen anstatt hinzugerechnet. Dieses Fehlverhalten führt natürlich zu einer vollständig anderen Dimensionierung des Elementes.

Der Internet Explorer für Apple Macintosh hat im Gegensatz zu den Windows-Versionen das korrekte Box-Modell implementiert. Während Opera bis Version 6 und ab Version 9 das korrekte Modell benutzt, verhält sich Opera von Version 7.0 bis Version 8.54 nur im Standards Mode richtig und imitiert damit das Verhalten des Internet Explorers 6 für Windows.

Der folgende Beispiel-Code dient zur Überprüfung, ob der verwendete Browser das Box-Modell korrekt unterstützt. Es wird ein Absatz mit festgelegten Werten für width, padding und border definiert. Der grüne Balken direkt darunter erhält den Wert für width, der sich gemäß dem Box-Modell als Gesamtbreite für den Absatz inklusive des Rahmens ergibt. Die Eigenschaften padding und border erhalten den Wert 0. Wird der Balken genauso breit angezeigt wie die Box inklusive Innenabstand und Rahmen, so unterstützt der verwendete Browser das korrekte Box-Modell. Der rote Balken erhält denselben Wert für width wie der Absatz. Haben roter Balken und Box dieselbe Breite, so weist der verwendete Browser den Box-Model-Bug auf.

Lösungen und Beispiele:

Es gibt verschiedene Herangehensweisen, um das hier beschriebene Problem zu lösen. Die einfachste Möglichkeit ist, die Seite flexibel genug zu gestalten, so dass es bei den Größen von Elementen nicht auf ein paar Pixel mehr oder weniger ankommt.

Damit auch der Internet Explorer 6 und die Opera-Versionen 7.0 bis 8.54 das korrekte Box-Modell verwenden, sollte unbedingt eine Doctype-Deklaration verwendet werden, die diese Browser in den Standards Mode versetzen. Aber bei der Erstellung neuer Seiten sollte dies sowieso selbstverständlich sein.

Sollte es tatsächlich auf pixelgenaues Design ankommen, bleiben somit noch die 5-er Versionen des Internet Explorers für Windows, die berücksichtigt werden wollen. Zwei Lösungsansätze sollen hier vorgestellt werden.

Verschachtelte Elemente:

Der »Trick« dieses Lösungsansatzes besteht darin, die Kombination von Wertzuweisungen für die Eigenschaften width und height auf der einen Seite sowie für padding und border auf der anderen Seite zu vermeiden. Dazu wird für ein äußeres Element die gewünschte Größe definiert. Einem inneren Element werden die gewünschten Rahmen-Eigenschaften und der Innenabstand zugewiesen. Die Höhe und Breite des eigentlichen Inhaltes, der in dem inneren Element untergebracht wird, passt sich nun automatisch an. Auf der Beispielseite dient der grüne Balken wieder als Indikator für die Funktionstüchtigkeit. Balken und Box inklusive des Rahmens müssen dieselbe Breite haben.

Beispiel mit verschachtelten Elementen

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
<head>
<title>DOCTYPE-Switch: Box-Model-Bug</title>

<style type="text/css">
div.ContentBox {
  width:440px;
}
div.BorderBox {
  padding:10px;
  border:solid 10px #009;
}
</style>

</head>
<body>

<div class="ContentBox">
  <div class="BorderBox">
    <p>Inhalt des Absatzes</p>
  </div>
</div>

</body>
</html>

Der Nachteil dieser Lösung ist die Notwendigkeit von zusätzlichem HTML-Code, der den Quelltext unübersichtlicher und unsauberer werden lässt.

Tantek-Hack

Ein weiterer Lösungsansatz, der eine reine CSS-Lösung ist und daher ohne zusätzlichen HTML-Code auskommt, ist der »Box Model Hack« von Tantek Çelik (»Tantek-Hack«). Dieser basiert auf einem Parsing-Bug der 5-er Versionen des Internet Explorers, der dazu führt, dass einzelne CSS-Deklarationen innerhalb eines Deklarationsblockes ignoriert werden.

p.content {
  width:440px;
  voice-family: "\"}\"";  /* alle folgenden Deklarationen      *
                           * innerhalb des Deklarationsblockes *
                           * werden von IE 5.x/Win ignoriert   */
  voice-family:inherit;
  width:400px;
}

Dieser Bug kann daher dazu ausgenutzt werden, um zunächst die Eigenschaften der Box gemäß dem falschen Box-Modell festzulegen. Anschließend wird die Größenangabe gemäß dem korrekten Box-Modell korrigiert. Im Internet Explorer 6 für Windows wurde der hier beschriebene Parsing-Bug beseitigt. Daher ist es unbedingt notwendig, dass bei Verwendung des Tantek-Hacks der Standards Mode verwendet wird, da sonst trotz allen Bemühungen der IE 6 eine falsche Größenangabe benutzt.

Für Browser, die zwar das korrekte Box-Modell beherrschen und auch sonst CSS 2-konform arbeiten, aber durch den »Tantek-Hack« ebenfalls durcheinandergebracht werden, wird eine weitere Regel eingeführt.

html>body .content {
  width:400px;
}

Diese Regel überschreibt mittels CSS 2-Selektoren den falschen Wert, wird aber von allen Internet Explorer Versionen unter Windows ignoriert.

Der komplette Quelltext sieht demnach wie folgt aus. Wieder dient der grüne Balken auf der Beispielseite zur Überprüfung der Funktionstüchtigkeit.

»Tantek-Hack«-Beispiel

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
<head>
<title>DOCTYPE-Switch: Box-Model-Bug</title>

<style type="text/css">
p.content {
  width:440px;
  padding:10px;
  border:solid 10px #009;
  voice-family: "\"}\"";
  voice-family:inherit;
  width:400px;
}
html>body .content {
  width:400px;
}
</style>

</head>
<body>

<p class="content">Inhalt des Absatzes</p>

</body>
</html>
Ausblick:

In den Entwürfen zu CSS 3 ist die Eigenschaft box-sizing enthalten. Mit dieser Eigenschaft kann bestimmt werden, nach welchem Modell die Dimensionen einer Box berechnet werden sollen.

box-sizing:content-box
Es wird das Box-Modell gemäß der CSS 2-Spezifikation verwendet. width und height legen die Größe des Inhaltes fest. Die Werte für padding und border-width werden dazugerechnet, um die Gesamtgröße des Elementes zu berechnen. content-box ist der voreingestellte Wert.
box-sizing:border-box
Die Werte für width und height legen die Gesamtgröße des Elementes fest. Die Werte für padding und border-width werden davon abgezogen, um die Größe des Elementinhaltes zu berechnen.

Mehrere Browser interpretieren bereits diese CSS 3-Eigenschaft, so zum Beispiel Internet Explorer 5 für Mac, Opera 7 und Konqueror seit Version 3.3.2. Mozilla interpretiert diese Eigenschaft in der Form -moz-box-sizing – durch die Vorsilbe -moz- als proprietäre Erweiterung gekennzeichnet, da box-sizing noch nicht in einer verabschiedeten Spezifikation enthalten ist. Mozilla interpretiert zudem padding-box als weiteren Wert: -moz-box-sizing:padding-box.

Der Internet Explorer für Windows und Safari interpretieren box-sizing nicht.

Das folgende Beispiel demonstriert die Verwendung von box-sizing bzw. -moz-box-sizing. Die zwei Boxen erhalten jeweils dieselben Werte für width, padding und border, aber unterschiedliche Werte für (-moz-)box-sizing. Wenn der verwendete Browser die zwei Boxen unterschiedlich groß darstellt, so unterstützt der Browser (-moz-)box-sizing. Die farbigen Balken zeigen an, welche Box-Größe sich gemäß welchem Box-Modell ergeben muss.

Anwendungsbeispiel für box-sizing

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
<head>
<title>DOCTYPE-Switch: Box-Model-Bug</title>

<style type="text/css">
p.content-box {
  box-sizing:content-box;
  -moz-box-sizing:content-box;
  width:400px;
  padding:10px;
  border:solid 10px #009;
}
p.border-box {
  box-sizing:border-box;
  -moz-box-sizing:border-box;
  width:400px;
  padding:10px;
  border:solid 10px #009;
}
</style>

</head>
<body>

<p class="content-box"> <!-- Inhalt des Absatzes --> </p>

<p class="border-box"> <!-- Inhalt des Absatzes --> </p>

</body>
</html>
Verwandte Themen:
Literatur:

Letzte Änderung des Inhaltes: 31.08.06