Zur Höhe von Listen bei gefloatetem Inhalt

Wegen einer Nachfrage hier noch ein Kommentar zur Höhenberechnung von dynamisch (!) generierten Listen, in denen die Höhe der Listenelemente und ihrer Inhalte (also irgendwelcher Tags innerhalb der <li>-Tags) nicht vorab bekannt sind und variieren können. Dies betrifft indirekt auch den letzten Beitrag in dieser Blog-Kategorie zur Generierung dynamischer Listen aus Datenbank-Sätzen. Dort hatten wir beschrieben, wie man mit Listen und dem Floaten des Inhalts formatierten Output für Datenbank-Abfragen erzeugen kann.

Eine Kollegin hat nun auf Basis des Beitrags ausprobiert, eine solche Liste unbekannter Höhe zu erstellen, bei der innerhalb der <li> mehrere Elemente (u.a. <div>-Elemente) mit "float:left;" positioniert worden waren. Als sie sich Rahmen um die <li> und das <ul>-Tag zeichnen ließ, war sie sehr erschrocken darüber, dass im Firefox der Rahmen des <ul>-Elements auf einen Strich zusammengezogen erschien. Die Höhe des <ul>-Block-Elements erschien also völlig falsch berechnet.

Komischerweise war das Verhalten im MS IE 7 ganz anders: Hier erschien die Border des <ul>-Tags richtig gezeichnet - also die Höhe des <ul>-Elementes aus den Inhalten der <LI>-Tags richtig berechnet. Warum diese große Diskrepanz zwischen den Browsern? Hat Firefox hier eine Macke? Eine Analyse des Codes zeigt dann dagegen, dass sich der MS IE eigentlich falsch verhielt und Firefox im Wesentlichen richtig!

Ein kurzer Blick auf das <li>-Elemente und die zugehörigen CSS-Anweisungen zeigte (verkürzt) Folgendes:

<ul style="width:30.0em;.........border: ...... ">
    <li style="width:30.0em; clear:left; float:left; border: ..... ; line-height:1.8em; ....">
        <div style="float:left; ....">graphisches Element</div>
        <div style="float:left; ...."><p>mehrzeiliger Text unbekannter Höhe</p></div>
    </li>
    <li style="width:30.0em; clear:left; float:left; border: ..... ; line-height:1.8em; ....">
    ......
    ......
</ul>

Die Listenzeilen wurden schön untereinander dargestellt; leider z.T. mit etwas falschen Abständen, sobald mehrzeilige Elemente auftauchten.

Der erste grundsätzliche Fehler liegt hier zunächst einmal in dem überflüssigen und falschen "float:left" für das <li>-Tag. Dass die Listenelemente überhaupt untereinander dargestellt werden, liegt hier nur an der Breitenbegrenzung des <ul>-Elementes!

Eine Elimination der "float"-Anweisung aus dem <li>-Tag ergab denn schon mal als ersten Fortschritt einen vertikal ausgedehnten Bereich für das <ul>-Element.

Leider hatte das <ul>-Element aber immer noch eine falsche Höhe und auch die Abstände zwischen den <li>-Elementen waren immer noch nicht gleichmäßig. Es hatte also den Anschein, dass die Höhe der <li>-Elemente und damit auch die resultierende Summe für das <ul>-Element nach wie vor falsch berechnet wurden - nämlich so, als ob nur die "line-height" relevant wäre.

Hier kommt nun der interessante Punkt:

Eine "float"-Anweisung hebt den gefloateten Bereich aus dem normalen Inhaltsverlauf (Kontext) des umgebenden Elementes heraus ! Man kann das näherungsweise mit dem Verhalten von absolut positionierten Elementen (z.B. DIVs) in ihrem Parent-Tag (z.B. einem mit "position:relative;" positionierten Container-DIV) vergleichen. Legt man für das umgebende Container DIV eine Höhe und Breite fest, so wird diese im Firefox exakt beachtet; die inneren DIVs ragen aber je nach Position und Größe völlig aus dem umgebenden Bereich heraus. Gleiches gilt für den Inhalt von <p>-Tags: Ist dieser zu groß und ein Text-Umbruch nicht möglich, so ragt der Text im Firefox aus dem umgebenden Block-Element (DIV) heraus. Dies ist vollkommen CSS-konform. (Der alte MS IE 6 verhält sich hier bei P-Tags noch ganz anders - nämlich so, dass er das umgebende DIV-Tag mit dem<P>-Tag ausdehnt.)

Wo liegt also im obigen Beispiel der Fehler? Warum wird die Höhe der <li>-Elemente nicht richtig berechnet? Antwort: Weil die float-Anweisung nicht innerhalb des <li>-Tags wieder aufgehoben wird!

Das Hinzufügen eines Dummy-Elements zum "Clearen" der float-Anweisung innerhalb des <li>-Tags genügt hierfür! Im obigen Beispiel bringt ein zusätzliches <p style="clear:left; ....">-Tag im <li>-Element alles ins Lot:

<ul style="width:30.0em;.........border: ...... ">
    <li style="width:30.0em; border: ..... ; line-height:1.8em; ....">
        <div style="float:left; ....">graphisches Element</div>
        <div style="float:left; ...."><p>mehrzeiliger Text unbekannter Höhe</p></div>
        <p style="clear:left; font-size:1px; line-height:1px; margin:0; "> </p>
    </li>
    ......
    ......
  </ul>

Natürlich wird dann auch die "clear"-Anweisung für das <li>-Element selbst überflüssig!

Merke also: Eine korrekte Höhenberechnungen von Elementen, die gefloateten Inhalt umschließen, setzt ein Aufheben der Float-Anweisung durch ein abschließendes (Dummy-) Element voraus.

Das gilt natürlich auch und vor allem für die im letzten Beitrag dieser Kategorie diskutierten dynamisch generierten Listen über PHP IT- oder ITX-Templates !