Die CSS-Alternative zu Float – display:inline-block

Als ich mal seit langem mal wieder ein Layout per CSS gestalten musste, kam die Frage auf, ob es nicht eine Alternative für die float-Angabe im CSS gibt, um Elemente dynamisch nebeneinander platzieren zu können. Denn mit folgenden Problemen hab ich bisher jedes mal zu kämpfen, wenn float im Spiel ist:

  • Ein ein mal gesetztes Float kann nur durch ein Clear aufgehoben werden (oder mit hässlichen Hacks, die aber in verschiedenen Browsern verschiedene Probleme machen)
  • Man kann immer nur ALLE floats (einer Richtung) aufheben. Also nicht nur das eine bestmmte, sondern im Zweiffel auch alle anderen, die man nicht erwischen wollte.
  • In so ziemlich jeder unterschiedlichen IE-Version gibt es damit unterschiedliche Fehler.
  • In allen Browsern brechen die “gefloeteten” Elemente aus ihrem umgebenden Container aus. Das muss man dann auch wieder mit Hacks irgendwie umgehen (und das ist, finde ich, das schlimmste Problem, weil am nervigsten)

Und wenn man es sich mal genau überlegt, wofür float eigentlich gedacht ist, ist es eigentlich klar, dass es so viele Probleme damit gibt. Ich denke es ist eben für Dinge wie ein Bild, was von Textblöckem umflossen wird und nicht um z.B. Navigationspunkte horizontal in einer Reihe anzuordnen oder ein 3-Spalten-Layout zu erstellen.

Und genau die zwei letztgenannten Anforderungen trieben mich dazu, mal in der Liste der CSS-Angaben zu suchen. Gefunden hab ich dort display: inline-block, was zwar auch nicht ohne Probleme ist, aber die sind örtlich begrenzt und eher handhabbar als ein außer Kontrolle geratenes Float.

Man definert mit dieser Angabe, dass sich das aktuelle Element nach “außen” wie ein inline-Element verhält, also keinen Umbruch hat und die Breite ggf. automatisch wählt, “innen” aber alles wie beim Block möglich ist. Also fixe Breitenangaben, wenn man denn will, margin und padding etc. Außerdem ist es extrem stressfrei, da es eben nur für genau dieses eine Element gilt und in dem umgebenden Block quasi eingesperrt bleibt. Also keine Nebenwirkungen außerhalb haben kann. Und will man den Elementfluss unterbrechen, um z.B. mehrere Zeilen zu haben, reicht ein einfaches <br/>.

Da das aber zu schön ist, gibts dann doch noch ein paar Probleme, nämlich folgende:

Whitespaces
Gibt es Zeichen zwischen den Elementen, z.B. Whitespaces, dann werden die, wie bei Fließtext auch, zwischen den Elementen dargestellt und erzeugen einen Abstand. Das kann man verhindern, in dem umgebeenden Block die Schriftgröße 0 zuteilt. Dazu muss es aber eben immer einen Umgebenden Block geben. Wenn man dann nicht für jedes enthaltene Element wieder definieren will, wie groß die Schrift dort wieder sein soll, muss man global eine absolute Schriftgröße angeben (* { font-size; 10pt; }). Alternativ kann man auch einfach keine Zeichen zwischen die Elemente setzen, auch keinen Zeilenumbruch, und braucht dann nicht mit den Schriftgrößen hantieren (der Quellcode ist dann aber unleserlich).
FireFox vor Version 2
Alle Versionen des FireFox vor Version 3 kennen die Angabe nicht. Allerdings gibt es dafür dort eine properitäre Angabe die genau das gleiche macht. Und die inline-block Angabe wird komplett ignoriert. Also kann man einfach VOR display:inline-block; die Angabe display:-moz-inline-box; setzen und alle FF sind glücklich
IE vor Version 8
Alle IE vor der Version 8 kennen die Angabe nicht. Allerdings ist display:inline; dort so fehlerhaft umgesetzt dass es sich exakt so wie display:inline-block verhält 🙂 Dumm ist nur, dass man nicht so einfach vorgehen kann wie beim FF kleiner v3 da die unbekannten Angaben trotzdem verwendet werden (was auch immer er dann macht, aber es ist falsch). Hier kann man entweder ConditionalComments benutzen, worurch die Angaben aber voneinander getrennt abgelegt werden, oder folgende Hacks:

Für IE 6
* html MEINELEMENT { display: inline; }
Für IE 7
*+ html MEINELEMENT { display: inline; }

Leider muss man BEIDE Angaben einzeln machen, da der eine Hack für den IE7 den für den IE6 unbrauchbar macht.

Unterschiedliche Höhen
Die Elemente, die man nebeneinander platzieren möchte, sind ja nicht immer alle gleich groß. Der Trick, das am einfachsten und effektivsten ist, ist einfach alle per vertical-align:top an der oberen Kante ausrichten.

Damit lassen sich für folgende Browser alle Unzulänglichkeiten ausbügeln, die mir bisher aufgefallen sind und es sieht dort überall gleich aus:

  • Opera seit mindestens v9.5
  • IE seit v6
  • FF seit mindestens v0.9

Hier mal ein Beispiel und der Code für eine Liste, deren Elemente nebeneinander stehen sollen und nach deren dritten Element eine zweite Zeile beginnen soll. Natürlich ist das für so ein einfaches beispiel viel einfacher per float umsetzbar, aber ich will gar nicht wissen, wie viele Zeilen CSS-Hacks ich schon geschrieben habe, um genau so einfache Sachen in größeren Layouts für den IE wieder gangbar zu machen.

Bsp: Display:inline-block in Aktion.


<style type="text/css">
/* solve whitespace-problem, part 1 */
* {
font-size: 12pt;
}
div#codeexdib {
/* solve whitespace-problem, part 2 */
font-size: 0;
/* only to show... */
border: solid 2px blue;
margin: 0;
padding: 0;
list-style: none;
}
div#codeexdib div {
/* FF before v3 solved */
display: -moz-inline-box;
display: inline-block;
/* force alignment */
vertical-align: top;
/* only to show... */
border: solid 2px red;
margin: 0;
padding: 1em;
}
/* IE6 solved */
* html div#codeexdib div {
display: inline;
}
/* IE7 solved */
*+ html div#codeexdib div {
display: inline;
}
</style>
<div id="codeexdib">
<div style="height:8em">Eins:1</div>
<div>Zwei:1</div>
<div style="width:4em">Drei:1</div>
<br/>
<div>Eins:2</div>
<div>Zwei:2</div>
</div>

Nachtrag: Ich hatte im Beispiel vormals UL und LI verwenden und darin ein BR, das funktioniert natürlich nicht weils nicht valide ist. Interessanterweise “mekern” nur alle IE (6 bis 8) und verschieben das BR in das davor liegende LI um wieder validen Code zu haben.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert