Bilder, Tabellen und seltsame Lücken


Dieses Dokument ist eine Übersetzung von Images, Tables, and Mysterious Gaps von Eric A. Meyer, Netscape Communications, Veröffentlicht am: 2002-03-04


Wenn man anfängt Webseiten zu schreiben sind die Chancen gut, daß man ein (oder auch mehrere) Designs hat, das sich auf das klassische Paradigma "verschachtelte Tabellen und viele Bilder" verläßt. Ob man Logos aufgesplittet hat, damit es gut ins Design passt oder ein Pixel große spacer-GIFs verwendet hat, die Prinzipien (und Gefahren) bleiben dabei identisch. Früher hat das funktioniert, denn Browser haben Tabellenzellen üblicherweise so hoch und breit gemacht wie das Bild, das sie enthielten.

Raus aus dem Jahr 2001: Es geht mit Riesenschritten weiter und es kommen standardbasierte Browser auf, die die Seiten nach den Regeln von HTML und CSS statt mit ihren eigenen Algorithmen, aufbauen. Wegen einer Seltsamkeit der CSS Spezifikation laufen Seiten, die sich auf ein präzises Layout mit kleinen Bildern und Tabellen verlassen, Gefahr eine optische Katastrophe zu werden. Alles, was dazu notwendig ist, ist ein moderner Browser und die richtige DOCTYPE und alles bricht auseinander!

Die Zutaten

Nehmen wir den Ausgangspunkt für die Probleme mal näher ins Auge und überlegen, warum das ein Problem ist. Wir fangen mit einem einfachen Fall an, Abbildung 1: eine einzellige Tabelle, die ein Bild enthält.

Abbildung 1.

Offensichtlich sind viele Designs eine Runde komplizierter als das, aber mehr brauchen wir zur Verdeutlichung des Problemes nicht. Ein Bild in einer Tabellenzelle -- das ist alles, was es braucht. Das ist ein Beispiel für klassisches Browserverhalten.

Schauen wir uns nun an, wie diese einfache Tabelle in einem modernen Browser aussieht, wenn die Seite eine "strict DOCTYPE" verwendet.

Abbildung 2.

Achtet auf den zusätzlichen Raum unter dem Bild in Abbildung 2. Das Markup der Tabelle und der Zelle bleibt unverändert -- es ist der Darstellungsmodus, der sich geändert hat. Anstatt das Bild "einzuschrumpfen", bildet der Browser jetzt die Linie auf der das Bild sitzt und zeigt diese mit an. Das Bild sitzt auf einer Linie, weil Bilder nach der Spezifikation inline Content sind. Das ist alles.

Wie Inline Content konstruiert wird

Um zu verstehen, was gerade passiert ist, nehmen wir nacheinander die Konstruktion einer line Box, die Plazierung eines Bildes innerhalb einer line Box und die Plazierung einer line Box innerhalb einer Tabellenzelle ins Auge. Als erstes eine einfache line Box mit Text wie in Abbildung 3.

Abbildung 3.

Der entscheidende Teil von Abbildung 3 ist die Schriftlinie (repräsentiert durch die blaue Linie) und ihre Plazierung in der line Box. Die exakte Plazierung der Schriftlinie hängt von der "default" Schrift für die line Box (dargestellt durch die rote Linie) ab, die vom font-family Wert für das Element, das die line Box enthält, festgelegt wird. Es ist für einen Autor nicht möglich die Position des Schriftlinie direkt zu verändern; wo sie ist, ist sie. Der Abstand unter der Schriftlinie wird "Unterlänge" genannt, denn das ist der Platz, wo sich die "Abstriche" von den kleinen Lettern wie "j", "y" oder "q" befinden. Abbildung 4 zeigt, was passiert, wenn ein Bild mit ins Spiel kommt.

Abbildung 4.

Schaut wo sich das Bild nach der Voreinstellung befindet: Die untere Linie des Bildes sitzt auf der Schriftlinie der line Box. Diese Plazierung kann mit vertical-align -- darüber reden wir gleich noch -- geändert werden, was aber fast nie jemand macht. In Abbildung 5 nehmen wir mal den Text weg und lassen nur das Bild stehen.

Abbildung 5.

Wir haben jetzt ein Bild, das auf der Schriftlinie einer line Box sitzt, die nur ein Bild enthält. Jetzt überlegen wir in Abbildung 6, was passiert, wenn wir diese Linie in eine Tabellenzelle setzen.

Abbildung 6.

Und jetzt sind wir da -- es erscheinen jetzt Lücken wo vorher keine waren. Es wird sogar noch schlimmer, wenn man kleine Bilder nimmt. Zum Beispiel eines, das einen Pixel groß ist, wie in Abbildung 7.

Abbildung 7.

Plötzlich erscheinen überall unerwartete kleine Lücken. Das ist genug, um einen Designer in den Wahnsinn zu treiben.

Gibt's eine Lösung?

Es gibt eine offensichtliche Lösung -- hört auf Layouts zu machen, die sich auf Tabellen und gespaltene oder ein Pixel große Bilder verläßt -- aber die dürfte für viele Designer zu unpraktisch erscheinen und es hilft nicht bei alten Seiten, die in neuen Browsern plötzlich auseinanderfallen. Es gibt eine weitere offensichtliche Lösung, die darin besteht sicherzustellen, daß das Dokument nicht den "strict rendering mode" auslöst. Das indem man eine HTML Transitional DOCTYPE ohne URL benutzt, or überhaupt keinen DOCTYPE angibt.

Während letztere Auswahl eine Möglichkeit ist, hilft das Autoren nicht, die sich mit xhtml Design, das immer den "strict rendering mode" auslöst, auseinandersetzen. Es gibt aber zwei grundlegende Herangehensweisen an dieses Problem in "strict" Dokumenten und eine Reihe von Wegen, um diese "Lösungen" zu erzeugen.

Bilder als Block deklarieren

Die erste Wahl, die bei den meisten grafiklastigen Designs funktionieren wird, ist das Bild vom Inlineelement zu einem Blocklevelelement zu machen. Wenn man das macht generiert es keine line Box mehr und das Problem verschwindet -- vorausgesetzt man hat nur das Bild in der Tabellenzelle. Im einfachsten Fall fügen wir die folgende Style Regel hinzu:


td img {display: block;}

Schaut das folgende Markup an und überlegt, was mit dieser Regel passiert:


<table cellspacing="0" cellpadding="0" border="0" width="500">
<tr><td><img src="nav1.gif"><img
src="nav2.gif"><img src="nav3.gif"><img
src="nav4.gif"><img src="nav5.gif"></td></tr>
<tr><td style="background: red;">
<img src="smallred.gif" height="1"  width="1"></td></tr>
<tr><td>
<p style="margin: 0.5em;">This is text in another cell of the
 table. Within the textthere is an icon <img src="icon2.gif">
 that indicates a link to another site. It's very worldly. Lorem
ipsum, dolor sit amet...</p></tr></table>

Wie wir in Abbildung 8 sehen, funktioniert das in einigen Fällen ganz gut, aber in anderen nicht mehr.

Abbildung 8.

Die dünne rote Linie zeigt, daß das ein Pixel spacer-GIF die Tabellenzelle tatsächlich nur ein pixel groß macht (wie der Designer es wollte). Leider sind jetzt auch die Bilder in der oberen Tabellenzelle Blocklevel und stehen deswegen übereinander anstatt nebeneinander.

Eine denkbare Lösung ist eine Klasse für die Bilder hinzuzufügen, die Blocklevelelement sein müssen und die Regel entsprechend anzupassen.


td img.decoration {display: block;}

Abhängig vom Design könnte das aber dazu führen, daß man eine ganze Menge Klassen für diesen einfachen Effekt hinzufügen müßte -- insbesondere, wenn viele ein Pixel Zellen verwendet werden, um bestimmte Effekte hervorzurufen. Wenn ihr Markup habt, das sich dazu eignet, könnte man die Regel auf die Tabellenreihe statt der Bilder anwenden. Ihr könntet also folgendes benutzen:


tr.decoration img {display: block;}

...und das Markup folgendermaßen anpassen:


<tr class="decoration"><td style="background: red;">
<img src="smallred.gif" height="1" width="1"></td></tr>

Das Resultat ist, daß nur das spacer-GIF Blocklevel ist und die anderen Bilder in Ruhe gelassen werden, wie in Abbildung 9 zu sehen.

Abbildung 9.

Alternativ könnte man die Klasse auch für die Tabellenzelle vergeben, falls das für Euch die bessere Wahl ist. In jedem dieser Fälle kann diese Herangehensweise unerwartete Nebeneffekte haben, wenn sich mehr als nur ein Bild in der Zelle befindet, wie in Abbildung 8 zu sehen.

Während wir immer noch die ein Pixel hohe Tabellenzelle haben, gibt es oben auch unerwünschten Abstand unter den Navigationsbuttons. Diesen Abstand loszuwerden kann ganz einfach sein, indem wir jedes Bild in eine eigene Zelle stecken und zum Blocklevelelement machen, aber um einen anderen Ansatz zu zeigen lassen wir sie mal in einer Zelle.

Das Ändern der vertikalen Ausrichtung

Die andere Hauptlösung ist das Bild ein Inlineelement zu lassen und das vertical alignment des Bildes in der line Box zu ändern. Man kann folgendes probieren:

td img {vertical-align: bottom;}

Das führt dazu, daß die Unterkante des Bildes mit der Unterkante der line Box und nicht mit der Schriftlinie übereinstimmt. Wie man in Abbildung 10 sehen kann, hat das den gewünschten Effekt: Der Abstand unter der Navigationsleiste ist verschwunden. Die Zelle, die lediglich der Dekoration dient ist aber immer noch zu hoch und die anderen Bilder sind im Vergleich zum umgebenden Text verschoben.

Abbildung 10.

Wir könnten wieder den Bildern, Zellen oder Reihen eine Klasse zuweisen, um diesen Effekt zu verkleinern. Das Problem mit ein Pixel großen Bildern aber bleibt, denn die diese umgebende line Box hat die Höhe der font-size für die Tabellenzelle und diese wird sich demnach nicht verkleinern. Das Bild bewegt sich an die Unterkante der Zelle, aber die Zelle verkleinert sich nicht und jedes Bild, das kleiner ist als die line Box hat umgebenden Freiraum -- wie das auch mit der roten Tabellenzelle passiert. Das ein Pixel Bild liegt auf der Unterkante der Zelle, aber die line Box ist wieder da und hat die Größe von normalem Text.

In Abbildung 11 wurde die font-size des Dokumentes mal erheblich vergrößert. Die Bilder der Navigation haben nach oben einigen Abstand und der rote Spacer ist auch größer geworden.

Abbildung 11.

Das ist bei dieser Herangehensweise schwer vermeidbar, denn Bilder sind nach wie vor Inlineelemente und nehmen auf die Gestaltung der line Box Einfluß. Wenn die line Box groß genug wird, werden Ränder rund um die Bilder erscheinen.

Zukunftsmusik und Lösungsansätze

Dank der gründlichen Implementation von CSS2 in Mozilla erfuhr das Problem von inline Bildern in Tabellenzellen, die unerwünschte Abstände hervorrufen die Aufmersamkeit der CSS-Arbeitsgruppe. Es gab viele Vorschläge, wie man das Problem lösen könnte und einer des vielversprechendsten Ansätze ist die Eigenschaft line-box-contain, die zur Einbindung in CSS3 vorgeschlagen wurde. Wenn diese Eigenschaft angenommen wird, kann jeder Browser (der das unterstützt) das traditionelle Verhalten mit dem Verkleinern emulieren ohne das man riskiert das andere Layout zu beeinflussen, indem man folgende Regel verwendet:


td {line-box-contain: font replaced;}  /* vorgeschlagen für CSS3 */

Es gibt in den aktuellen Arbeitsvorschlägen zu CSS3 aber auch weitere Lösungsansätze, wie zum Beispiel die line-height-policy. Offentsichtlich ist: je früher eine Lösung gefunden wird, desto glücklicher werden auch die Autoren sein.

Empfehlungen

Solange die CSS3 Unterstützung fehlt ist es schwer eine generelle Herangehensweise zu empfehlen, denn die beste Lösung für ein Dokument hängt überwiegendvon dessen Struktur ab. Wenn das Dokument "transitional" Markup verwendet, stellt sicher, daß die DOCTYPE passt und keine URI hat. Das verhindert bei Browsern das sogenannte "strict" rendering und die Probleme werden auf diese Weise umgangen. Wenn ihr "strict" Markup verwendet oder aus anderen Gründen das "strict" rendering benutzt, dann denkt an folgende Richtlinien:

Mit einer umsichtigen Mischung der Herangehensweisen und einer Minimierung von Tricks mit einem Pixel großen Bildern -- die in einem CSS fähigen Browser sowiso überflüssig sind -- ist es gut möglich diesem seltsamen Effekt von Standardunterstützung aus dem Weg zu gehen. Die beste Lösung könnte sein, daß man sicherstellt, daß Bilder sich immer einzeln in einer Zelle befinden und sie dann zu Blocklevelelementen zu machen, aber das hängt - wie immer - vom Design des Autors ab.

Anmerkung:

In Mozilla 1.0.1+ gibt es einen "almost standards" Mode, der genau dieses Thema berührt. Mit diesem beschäftigt sich die Ergänzung "Geckos Beinahe-Standard-Modus" von Lars Trebing.


Web-Technik und Anleitungen.