Dynamische Höhensteuerung mehrer DIVs

Im HTML/CSS2-Bereich gibt es immer mal wieder Dinge, von denen man glaubt, man bekäme sie aus grundsätzlichen Erwägungen nie vernünftig hin. Probleme, über die ich immer wieder stolpere, sind Kombinationen aus mehreren Anforderungen:

  • vertikal expandierbare Webseiten mit gefloateten und/oder mehreren übereinander liegenden DIV-Layern,
  • gegenseitige Höhensteuerung oder Höhen-Synchronisation unabhängiger, vertikal frei expandierbarer DIV-Layer mit vorab unbekanntem (!) Inhalt und damit initial nicht definiertem Wert der Höhe,
  • em-skalierbare Webseiten mit Layern, in denen ebenfalls em-skalierbare Hintergrundsbilder untergebracht werden müssen.

Warum sind solche Anforderungskombinationen problemträchtig? Dies liegt daran, dass die Anforderungen zum Teil im Widerstreit miteinander liegen.

Konkurrierende Anforderungen unter CSS2 bei unbestimmten Höhen, die erst zur Laufzeit festgelegt werden

Schwierigkeiten entstehen vor allem dann, wenn es in der DIV-Schichtung Layer gibt, deren Höhe erst zur Laufzeit durch eingefügte Elemente - z.B. Text - festgelegt wird und nicht von Anfang an bestimmt ist (dynamische Höhenfestlegung). Solche Situationen tauchen typischerweise immer dann auf, wenn man DIVs mit Datenbank-Inhalten füllt. Dies ist u.a. typisch für Content-Management-Systeme und zugrunde liegende Template-Strukturen. So auch bei unserem hauseigenen CMS, das auf einem Framework beruht, welches sich ITX-Templates zunutze macht.

Bei der Generierung dynamischer Webseiten hängt die Menge des Inhalts und damit auch die vertikale Ausdehnung mancher DIVs sowie ggf. auch der gesamten Web-Seite davon ab, was der Kunde eingepflegt hat. Das kann man natürlich nicht im vorhinein wissen. Die sich zur Laufzeit ergebende DIV-Höhe mit Javascript zu bestimmen, finde ich aber einfach unelegant. Lässt man Javascript aber außen vor, wird es schwierig,

  • die Höhe von Seitenleisten mit unabhängigen DIVs zur Laufzeit zu synchronisieren,
  • die Höhe verschiedener DIVs in einer Layerschichtung in z-Richtung oder in gefloateten Kontexten zur Laufzeit zu synchronisieren
  • oder aber den sichtbaren Bereich "em"-skalierbarer Hintergrundsbilder zusammen mit einem DIV, in das erst zum Zeitpunkt der Seitengenerierung Texte eingelesen werden, auf einen initial unbekannten Höhenwert wachsen zu lassen.

So kann man etwa absolut positionierte DIVs per CSS über die "z-index"-Anweisung gut übereinander schichten. Damit entkoppelt man sie dimensionsmäßig aber auch voneinander!

Oftmals soll gerade der oberste Layer einen Text tragen, dessen Länge nicht von vornherein bekannt ist. Dennoch soll die Textlänge letztlich die sich ergebende vertikale Ausdehnung des umgebenden DIV-Layers, die Höhenausdehnung der gesamten Seite und verschiedener anderer dort enthaltener Layer - z.B. mit Hintergrundsbildern - bestimmen. Das geht mit absolut positionierten DIVs allein überhaupt nicht!

Hinzu kommt, dass gefloatete DIVs, die auf vielen Web-Seiten eingesetzt werden, ebenfalls eine eigene Layerstruktur definieren, so dass besondere Vorkehrungen getroffen werden müssen, wenn umgebende DIVs auf eine potentielle vertikale Expansion der gefloateten DIVs reagieren sollen.

Noch problematischer wird es, wenn man zusätzlich alle Elemente einer Website in "em"-Einheiten definiert hat. Ein Ziel eines solchen Vorgehens kann es sein, die gesamte Seite auf Knopfdruck mit vordefinierten Faktoren zu skalieren. Dies ist jedoch mit Hintergrundsbildern, die per CSS-Anweisung "background-image" z.B. in DIV-Layer eingesetzt wurden, nicht möglich. Solche Hintergrundsbilder skalieren nämlich nicht mit. Womit die Behandlung "em"-skalierbarer Hintergrundsbilder wieder zu einem Lösungsansatz mit per z-Index übereinander geschichteten DIVs führt.

Betrachten wir einmal das Beispiel einer über den z-Index geschichteten Layer-Struktur, wie sie in der nachfolgenden Abbildung dargestellt ist:

div_layer

Die Layer mit unterschiedlichem z-Index wird man in der Regel mit CSS-Anweisungen der Form

position:absolute; z-index:n;"

mit wachsendem "n" übereinanderlegen. Es ist dann natürlich einfach, das Hintergrundsbild ebenso wie die Größe des halbtransparenten Layers "em"-skalierbar zu machen. Die Transparenz erreicht man entweder über die CSS-Anweisung "opacity:0.x;" - was inzwischen die meisten Browser verstehen - oder aber über browserspezifische Anweisungen (Browserweichen). Kennt man die Größe - Breite und Höhe - des Bereiches, den der Text einnehmen wird, von vornherein, hat man alles unter Kontrolle.

Typischer Code für eine einfache Website mit solchen Elementen sieht dann wie folgt aus:

<div id="cont" style="position:relative; width:50.0em; height:60.0em; background-color:#CCC; ">
    <div id="bg_img" style="position:absolute; top:0; left:0; width:53.0em; height:60.0em; z-index:1;"><img src="...." style="width:100%; ....."></div>
    <div id="bg_transp" style="position:absolute; top:0; left:0; width:53.0em; height:60.0em; background-color: #FFF; opacity:0.7; z-index:2;"></div>
    <div id="bg_transp" style="position:absolute; top:0; left:0; width:53.0em; height:60.0em; z-index:3;"><p>LANGER TEXT</p></div>
</div>

Man kann natürlich die Bilddimensionen auch explizit in "em"-Einheiten vorgeben. Hier passt dann natürlich alles, weil wir die Höhen von vornherein explizit so festlegen, dass der bekannte Text hinein passt. Alternativ legt man die Höhen der Seitenelemente von vornherein fest und aktiviert bei zu langem Text einen vertikalen Scrollbar.

Wir allerdings wollen etwas anderes: Verschiedene Seitenelemente sollen sich höhenmäßig und synchron an einen Textinhalt beliebiger Länge anpassen.

Hinweis:
Hier wie in den nachfolgenden Beispielcodes werden wir CSS-Vorgaben immer direkt in den TAGs angeben. Im realen Leben würde man natürlich CSS-Klassen definieren.

Anforderungen an automatische Höhenbestimmungen zur Laufzeit bei gleichzeitiger em-Skalierung von Hintergrundsbildern

Nun stellen genauer folgende Anforderungen:

  1. Wir möchten eine dynamische Skalierung aller (!) Seitenelemente mit der Schriftgröße, die für das BODY-Tag definiert wird ("em"-Skalierung). Dies soll auch für eventuelle Hintergrundsbilder gelten.
  2. Die Höhe eines zentralen Textbereiches der Webseite soll durch die beliebige Länge eines unbekannten (!) Textes aus einer Datenbank definiert werden.
  3. Wir möchten eine dynamische Expansion der gesamten Webseite in vertikaler Richtung mit der Höhe des Textbereichs.
  4. Die Layer für das Hintergrundsbild, einen ggf. zwischengeschalteten semitransparenten Layer sowie für den Text unbekannter Länge sollen in z-Richtung übereinander geschichtet sein.
  5. Wir möchten gleichzeitig mit der dynamischen Expansion des Text-DIVs auch eine entsprechende Höhen-Expansion des halbtransparenten DIV-Layers.
  6. Wir möchten gleichzeitig eine dynamische Expansion des DIV-Layers, der das Hintergrundsbild enthält. Dabei soll das Bild selbst eine wesentlich größere Basishöhe als das eingrenzende DIV haben. Das DIV, welches das IMG-Tag beinhaltet, soll automatisch die gleiche Höhe annehmen, wie das DIV mit dem Textbereich. Ferner soll dieses DIV während seines vertikalen Wachstums einen entsprechenden Bereich des von Haus aus größeren "Hintergrundsbildes" in vertikaler Richtung freigeben und den Rest abschneiden.
  7. Wir möchten, dass die vertikale Expansion der gesamten Seite auch dann gegeben ist, wenn sich die dargestellte Layer-Schichtung in z-Richtung innerhalb eines gefloateten DIV-Bereichs befindet.
  8. Wir möchten ferner, dass die Hintergrundsbereiche von optisch unabhängigen Seitenbereichen, die über gefloatete DIVs erzeugt wurden, synchron die Höhe annehmen, die durch einen zentralen Textbereich innerhalb eines der gefloateten DIVs zur Laufzeit vorgegeben wird.

Anforderung 1 ist nicht mit CSS-definierten Hintergrundsbildern (background-image) erfüllbar. Also müssen die Bilder in eigenen DIVs mit niedrigem z-Index untergebracht werden.
Anforderung 2 lässt sich einfach dadurch erfüllen, dass man die Höhe des entsprechenden relativ positionierten DIVs offen lässt.
Anforderung 3 läuft darauf hinaus, dass sich mehrere ineinander geschachtelte DIVs an der Höhe des Text-DIVs orientieren, dessen Ausdehnung erst zur Laufzeit bestimmt wird. Dies setzt einerseits zwingend den Einsatz relativ positionierter DIVs für den Text und dessen Container voraus (position:relative;).
Anforderung 4 spricht insgesamt für absolut positionierte und per z-Index geschichtete DIVs.
Die Anforderungen 5) und 6) bedeuten, dass das DIV mit dem Text die Höhe der darunter liegenden DIVs definiert. Das geht aber mit unabhängigen, absolut positionierten DIVs nicht ohne weiteres !
Anforderung 7 erschwert die Aufgabe zusätzlich, da sich die Höhe gefloateter DIVs nicht automatisch auf die umgebender DIVs auswirkt.
Anforderung 8 ist mehr als problematisch, da gefloatete Bereiche nicht gegenseitig ihre Höhen festlegen können.

Das schwierigste Problem liegt zunächst eindeutig in Anforderung 5. Wie kann ein Layer mit Inhalt unbekannter Länge die Höhe darunter liegender - notwendigerweise - absolut positionierter DIVs vorgeben? Auf die Lösung bin ich Zufall gestoßen, als ich mich mal aus einem anderen Grund mit der Vererbung in CSS2 (inherit-Anweisung) befassen musste.

Absolut positionierte DIVs können die dynamisch berechnete Höhe eines umgebenden relativ positionierten DIVs annehmen

Der erste Schlüssel für einen Lösungsansatz ist folgender:

Absolut positionierte DIVs können die Höhe eines umgebenden relativ-positionierten DIVs über die "inherit"-Anweisung oder Anweisungen der Art "height:100%;" übernehmen, sobald die Höhe des relativ positionierten DIVs zur Laufzeit von der Engine des Browsers bestimmbar ist oder aber über eine Analyse des Platzbedarfs seines Inhalts berechnet wurde.

Zum Beispiel nimmt in folgendem Beispiel dass "inner"-DIV die vorgegebene Höhe des "cont"-Divs an. :

<div id="cont" style="position:relative; height:40.0em; width:50.0em;">
    <div id="inner" style="position:absolute; top:0px; left:10.0em; height:100%; width:20.0em; background-color:#F00; "></div>
</div>

Natürlich kann man die Höhe des inneren DIVS über eine geeignete %-Angabe auch anders mit der Höhe des umgebenden DIVs mitskalieren lassen.

Im Fall dynamisch generierten Inhalts ist die gewünschte Höhe der DIVs aber leider nicht vorab bekannt. Die Höhe des Inhalts eines absoluten DIVs kann in W3C-konformen Browsern zudem nicht die Höhe eines umgebenden relativ oder auch absolut positionierten Container-DIVs festlegen. Wir können den gewünschten Inhalt also eigentlich nicht wie im obigen grafischen Beispiel in absolut positionierte DIVs einfüllen.

Höhenfestlegung verschachtelter DIVs zur Laufzeit - der umgebende Container als Vermittler der Höhe

Was aber, wenn man ein inneres, relativ positioniertes DIV verwendet, um die Höhe des umgebenden relativ positionierten DIVs festzulegen? Würde sich diese Höhenfestlegung dann indirekt auch auf das absolut positionierte, innere DIV auswirken?

Tatsächlich funktioniert Folgendes:

<div id="cont" style="position:relative; width:50.0em; background-color:#CCC; ">
    <div id="in_rel" style="position:relative; width:80%; height:200px; background-color: #999; margin-left:auto; margin-right:auto; "></div>
    <div id="in_abs" style="position:absolute; top:0px; left:20.0em; width:10.0em; height:80%; background-color: #F00;"></div>
</div>

Wir können also die Höhe des inneren absolut positionierten DIVs durch ein auf gleicher Verschachtelungs-Ebene befindliches relativ positioniertes DIV steuern. Der umgebende DIV-Container wirkt dabei quasi als Vermittler der Höhe!

[Einschränkung: Auf der MS Seite geht das erst ab dem MS IE7, nicht aber mit dem MS IE6!]

Hier das Ergebnis für moderne Browser (wobei arme IE6-Anwender natürlich nichts Vernünftiges zu Gesicht bekommen werden) :

Nun sind wir nur noch einen kleinen Schritt von unserem ersten Ziel entfernt. Wir unterlassen eine Festlegung der Höhe des inneren relativ positionierten DIVs "<div id="in_rel" >" per CSS und steuern die Höhe dieses DIVs vielmehr dynamisch durch seinen Inhalt.

Also z.B. folgendermaßen:

<div id="cont" style="position:relative; width:50.0em; background-color:#CCC; ">
    <div id="in_rel" style="position:relative; width:80%; background-color: #999; margin-left:auto; margin-right:auto; ">
        <p>Lorem ipsum dolor sit amet, ... LANGER TEXT ... ut laoreet dolore magna aliquam erat volutpat.</p>
    </div>
    <div id="in_abs" style="position:absolute; top:0px; left:20.0em; width:10.0em; height:80%; background-color: #FEFE99;"></div>
</div>

Auch dies geht offenbar, wie man testen kann:

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril elenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, ed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Der vertikale Platzbedarf des Textes wird vom Browser erst zur Laufzeit bestimmt. Dies gilt selbst dann, wenn wir den Text in unserem Beispiel vorgeben und nicht aus einer Bank auslesen haben lassen. Entscheidend ist, dass der Browser die benötigte Höhe des umgebenden DIVs erst zur Laufzeit ermitten muss, weil sie nicht per "height"-Anweisungen vorgegeben ist ! Daher zeigen auch die nachfolgenden Beispiele durchaus auch, wie man im Fall von dynamisch ermitteltem Content vorgehen kann.

Der Inhalt des DIVs mit der id="in_rel" bestimmt also zur Laufzeit dessen Höhe. Die Höhe des DIVs mit der id="in_rel" wiederum wird vom umgebenden relativ positionierten Container-Div (id="cont") übernommen. Nach dessen vom Browser ermittelter Höhe richtet sich dann das enthaltene, innere absolut positionierte DIV mit der id="in_abs".

Schichtung relativer und absolut positionierter DIVs in aktuellen Browsern

Nun gefällt uns die Schichtung noch nicht - wir wollen ja eigentlich das DIV mit dem Text im Vordergrund haben. Ferner müssen wir die Breite des absolut positionierten DIVs so anpassen, dass es als Hintergrund dienen kann. Also :

<div id="cont" style="position:relative; width:50.0em; background-color:#CCC; ">
    <div id="in_rel" style="position:relative; width:80%; margin-left:auto; margin-right:auto; padding:2.0em 0 2.0em 0; z-index:10;">
        <p> Lorem ipsum dolor sit amet, ... LANGER TEXT ... ut laoreet dolore magna aliquam erat volutpat. </p>
    </div>
    <div id="in_abs" style="position:absolute; top:0; left:0; width:100%; height:100%; background-color: #FEFE99; z-index:1;"></div>
</div>

Hinweis: Man beachte die z-Index-Werte! Bei älteren Browsern - speziell beim MS IE - musste man übrigens höllisch aufpassen, wenn man die gleichzeitige Schichtung relativ und absolut positionierter DIVs richtig hinbekommen wollte. Im besonderen hing beim MS IE ( < Version 8 ) das Ergebnis davon ab, in welcher Reihenfolge die DIVs im HTML-Code definiert wurden. Es empfahl sich, innerhalb des Codeblocks für einen Container zuerst die relativ positionierten DIVs und dann die absolut positionierten anzugeben. Dies ist heute in der Regel nicht mehr nötig.

Dass das Übereinanderlegen von relativen und absoluten DIVs in modernen Browsern bei gleichzeitiger dynamischer Höhensteuerung des absolut positionierten DIVs durch den umgebenden Container funktioniert, sieht der Leser hoffentlich am nachfolgenden Ergebnis:

Testbeispiel - relatives DIV über absolutem DIV und Höhenvermittlung durch den Container

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril elenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, ed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Hinweis: Alle Beispiele/Ergebnisse setzen die in diesem Beitrag diskutierten HTML-Code direkt auf der vorliegenden Blog-Seite um. Man kann sich den Code also auch aus dem Quelltext kopieren.

Testbeispiel zur inhaltsabhängigen Höhenfestlegung verschachtelter DIVs mit Hintergrundsbild

Nun unterlegen wir den Text noch mit einem Hintergrunds-Bild:

<div id="cont" style="position:relative; width:50.0em; background-color:#CCC; ">
    <div id="in_rel" style="position:relative; width:80%; margin-left:auto; margin-right:auto; z-index:10; padding:2.0em 0 2.0em 0; ">
        <p> Lorem ipsum ......</p>
    </div>
    <div id="in_abs" style="position:absolute; top:0; left:0; width:100%; height:100%; z-index:1;">
        <img src="...." style="width:100%;">
    </div>
</div>

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril elenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, ed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

yellow_bryce

Bei einer Höhenveränderung des Textes (hier durch künstliche Umbrüche erzwungen) passt sich die Umgebung automatisch an und der vertikal längere Text gleitet über das Hintergrundsbild weg, das dabei in entsprechender Länge enthüllt wird ( vergl. mit Anforderung 6 weiter oben ) :

Lorem ipsum dolor sit amet, consectetur adipisici elit,
sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquid ex ea commodi consequat.
Quis aute iure reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint obcaecat cupiditat non proident,
sunt in culpa qui officia
deserunt mollit anim id est laborum.
Duis autem vel eum iriure dolor in hendrerit in vulputate
velit esse molestie consequat, vel illum dolore eu
feugiat nulla facilisis at vero eros et accumsan
et iusto odio dignissim qui blandit praesent luptatum zzril
delenit augue duis dolore te feugait nulla facilisi.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
ed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat.

yellow_bryce

In vielen Fällen muss man das Hintergrundsbild abdämpfen, um die Lesbarkeit zu verbessern. Einen für alle gängigen Browser funktionierenden Semi-Transparenz-Layer hinzuzufügen, überlassen wir dem Erfindungsreichtum des Lesers. Das nachfolgende Code-Beispiel funktioniert zumindest im aktuellen Firefox und demonstriert das Prinzip:

<div id="cont" style="position:relative; width:50.0em; background-color:#CCC; ">
    <div id="in_rel" style="position:relative; width:80%; margin-left:auto; margin-right:auto; z-index:10; padding:20px 0 20px 0; ">
        <p> Lorem ipsum ......</p>
    </div>
    <div id="in_abs" style="position:absolute; top:0; left:0; width:100%; height:100%; z-index:1; background-color:#FFF; opacity:0.70; "></div>
    <div id="in_abs" style="position:absolute; top:0; left:0; width:100%; height:100%; z-index:1;">
        <img src="...." style="width:100%;">
    </div>
</div>

Lorem ipsum dolor sit amet, consectetur adipisici elit,
sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquid ex ea commodi consequat.
Quis aute iure reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint obcaecat cupiditat non proident,
sunt in culpa qui officia
deserunt mollit anim id est laborum.
Duis autem vel eum iriure dolor in hendrerit in vulputate
velit esse molestie consequat, vel illum dolore eu
feugiat nulla facilisis at vero eros et accumsan
et iusto odio dignissim qui blandit praesent luptatum zzril
delenit augue duis dolore te feugait nulla facilisi.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
ed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat.

yellow_bryce

Hinweis: Im MS IE muss man halt mit proprietären CSS-Anweisungen der Art "filter: alpha(opacity=70);" arbeiten!

Höhensteuerung gekoppelter DIVs zur Laufzeit und gefloatete Container

Nun das Ganze in einer Umgebung mit floatenden Seitenbereichen. Eine typische Anwendung ist folgende:

Wir wollen in einem "right"-gefloateten Layer zur Laufzeit einen Text noch unbekannter Länge unterbringen. Dieser soll jenseits einer Minimalhöhe die vertikale Ausdehnung der gesamten Web-Seite bestimmen (welche im nachfolgenden Beispiel über ein umfassendes DIV repräsentiert wird). In einem "left"-gefloateten DIV soll ferner eine vertikale Menü-Struktur untergebracht werden, deren Länge typischerweise kürzer als die des Textbereichs (rechts) ist. Der Hintergrund des Menübereichs soll sich jedoch parallel zur Länge des Textbereiches ausdehnen. Der Anspruch ist also:

Der Textbereich in einem "right"-gefloateten Bereich determiniert die Höhe des Hintergrunds eines "left"-gefloateten Bereichs!

Eigentlich unmöglich, denkt man! Mit folgendem Trick geht es aber doch - wie das Beispiel zeigt ! Und es geht auf der MS-Seite ab dem MS IE7.

Testbeispiel mit gefloateten DIvs und gekoppelter vertikaler Ausdehnung

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

yellow_bryce

Links erkennt man den gelben Hintergrund eines Menübereichs. Der Menütext befindet sich in einem "left"-gefloateten Container-DIV. Der gelbe Hintergrundsbereich - ein DIV (in dem sich auch ein Bild befinden könnte) - dehnt sich auf exakt die Höhe aus, die der Textbereich rechts in einem "right"-gefloateten Container-DIV vorgibt. Gleichzeitig folgt die gesamte Webseite der Größe des Textes im rechten Float-Container. Alles klar?

Natürlich haben wir ein wenig unterschlagen: Nachfolgend wird das DIV für den Menübereich mal mit einer blauen "Border" umgeben:

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

yellow_bryce

Wir sehen, dass die Größe des left-gefloateten Bereichs kleiner ist als die des Hintergrunds. Also steuert der rechte Textbereich nicht wirklich die Höhe des links gefloateten Bereichs. Und dennoch erhält der linksseitige gelbe Hintergrund die richtige Höhe ....

Wie sieht der Code dazu aus?

<div id="bsp_cont" style="position: relative; margin-left: auto; margin-right: auto; width: 50.0em; border: #666 0.4em solid; background-color: #EEE; ">
    <div id="float_cont" style="position:relative; min-height:5em; border:2px #0F0 solid;">
        <div id="menu_left" style=" position:relative; float:left; width:12.6em; padding:1em; border: #CCC 0.2em solid; z-index:2; ">
                <p style="margin:0;">menu<br>menu<br>menu<br>menu</p>
        </div>
        <div id="main_right" style="position: relative; float:right; width:25.6em; border: red 0.2em solid; background-color:CCC; z-index: 2; ">
             <div id="txtbox_right" style="position:relative; color:#000; z-index:3; padding:0.6em; ">
                <p style="margin:0;">Lorem ipsum dolor sit amet, ....... mollit anim id est laborum.</p>
            </div>
            <div id="transp" style="position:absolute; top:0; left:0; width:100%; height:100%; background-color: #FFF; opacity:0.7; filter: alpha(opacity=70); z-index:2; "></div>
            <div id="bg_img" style="position:absolute; top:0; left:0; height:100%; width:100%; overflow:hidden; z-index: 1; ">
                <img src='https://linux-blog.anracom.com/wp-content/uploads/2011/07/yellow_weit_ext_1_640.jpg' alt='yellow_bryce' style="width:100%;">
            </div>
        </div>
        <p style="clear: both; line-height: 0; font-size: 0; height: 0; margin: 0; padding: 0;"> </p>
        <div id="bg_left" style="position:absolute; top:0; left:0; width:15.0em; height: 100%; border: red 1% solid; background-color: #FEFE77; color: blue; z-index:1;"></div>
    </div>
    <div id="bsp_footer" style="position:relative; background-color: #CCC; width: 49.6em; height:2.0em; text-align:center; border: green 0.2em solid; margin-top:1.0em; margin-bottom:0; "><p style="margin:0;">Footer</p></div>
</div>

Man erkennt nach eine wenig Analyse vier Punkte:

  • Im rechts gefloateten Container-DIV mit der id="main_right" nutzen wir das oben besprochene Muster zur Höhenvermittlung zwischen einem relativ positinierten DIV (id="txtbox_right") für den Text, dessen vertikaler Platzbedarf erst zur Laufzeit bestimmt wird, und den absolut positionierten DIVs (id="transp" und id="bg_img") für die Gestaltung des zugehörigen Hintergrunds.
  • Die gesamte vertikale Ausdehnung des äußeren Containers mit der id="bsp_cont" ist zunächst unbestimmt. Sie wird festgelegt durch die Höhe des DIV-Containers mit der ID id="float_cont" plus der Höhe des DIVs mit der id="bsp_footer". Die Höhe des DIVs mit der id="float_cont" hängt ab von den beiden beinhalteten und gefloateten DIVs. Dass deren Höhe nach außen an das umgebende DIV (id="float_cont") weitergegeben wird, ist dem <p>-Tag zu verdanken, dass noch innerhalb des Containers die Float-Strukturen (eig. Ebene) per "clear"-Anweisung beendet.
  • Die Höhe des äußersten Containers mit der id="bsp_cont" hängt ab von der Höhe des DIVs mit der id="float_cont". Dessen Höhe wiederum wird durch die Höhe des gefloateten DIVs mit der id="main_right" bestimmt. Die Höhe des DIVs mit der id="main_right" wird dagegen definiert durch die Höhe des DIVs mit der id="txtbox_right". Und dessen Höhe hängt von einem Textinhalt ab, den wir in CM-Systemen des realen Lebens erst (mit PHP oder Java) aus einer Datenbank auslesen würden. Obwohl wir hier im Beispiel einen Text vorgeben, wird auch dessen Höhe erst vom Browser zur Laufzeit berechnet.
  • Aus logischen Konsistenzgründen kann es nicht so sein, dass ein gefloatetes Element die Höhe eines anderen gefloateten Elements festlegt. Also kann man die Höhe des Hintergrunds auf der linken Seite nicht direkt über die Höhe des "left"-gefloateten DIVs beeinflussen. Der Trick besteht nun darin, ein weiteres DIV in dem DIV-Container mit der id="float_cont" zu positionieren und zwar mit "position:absolute; top:0; left:0;" ! Denn dieses absolut positionierte DIV mit der id="bg_left" kann die dynamisch ermittelte Höhe des umgebenden relativ positionierten Containers übernehmen. Das war ja genau das, was wir schon weiter oben gesehen hatten !
  • Im MS IE7 ist die Reihenfolge der Codezeilen für gefloatete, relativ oder absolut positionierte DIVs in einem Container für die Ergebnisdarstellung leider nicht egal! Anweisungen für absolut positionierte DIVs sollten auf Anweisungen für relativ positionierte DIVs und auch nach Anweisungen für gefloatete DIVs folgen. Für den MS IE 7 ist es in unserem Beispiel also wichtig, dass die Zeile für das absolut positionierte DIV mit der id="bg_left" im Code erst nach (!) den Zeilen für die gefloateten DIVs und nach dem P-Tag mit der "clear"-Anweisung gesetzt ist. Eine Positionierung vor den Zeilen mit den gefloateten DIVs führt zu einer fehlerhaften Abarbeitung. Im MS IE8 ist dieses Problem behoben. (Wer ganz auf Nummer sicher gehen will, der umgibt die Zeilen für die gefloateten DIVs und das P-Tag auch noch mit einem weiteren kapselnden DIV, das dann relativ positioniert werden muss.)

Will man dagegen eine Lösung haben, bei der auch der links gefloatete Textbereich - falls er denn länger als der rechte werden würde - die Gesamtausdehnung steuern soll, so muss man den obigen HTML-Code etwas umstellen:

<div id="bsp_cont" style="position: relative; margin-left: auto; margin-right: auto; width: 50.0em; border: #666 0.4em solid; background-color: #EEE; ">
    <div id="float_cont" style="position:relative; min-height:5em; border:2px #0F0 solid;">
        <div id="menu_left" style=" position:relative; float:left; width:12.6em; padding:1em; border: blue 0.2em solid; z-index:3; ">
            <p style="margin:0;">menu<br>menu<br>menu<br> menu<br>menu<br>menu<br>menu<br>menu<br>menu</p></div>
        <div id="main_right" style="position: relative; float:right; width:25.6em; border: red 0.2em solid; background-color:CCC; z-index: 3; ">
            <div style="position:relative; color:#000; z-index:2; padding:0.6em; ">
                <p style="margin:0;">Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p></div></div>
        <p style="clear: both; line-height: 0; font-size: 0; height: 0; margin: 0; padding: 0;"> </p>
        <div id="bg_left" style="position:absolute; top:0; left:0; width:15.0em; height: 100%; border: red 1% solid; background-color: #FEFE77; color: blue; z-index:1;"></div>
        <div id="bg_right" style="position:absolute; top:0; right:0; width:25.6em; height: 100%; overflow:hidden; z-index:1;"><img src='.....' alt='yellow_bryce' style="width:100%;"></div>
        <div style="position:absolute; top:0; right:0; width:25.6em; height:100%; background-color: #FFF; opacity:0.7; filter: alpha(opacity=70); z-index:2; "></div>
    </div>
    <div id="bsp_footer" style="position:relative; background-color: #CCC; width: 49.6em; height:2.0em; text-align:center; border: green 0.2em solid; margin-top:1.0em; margin-bottom:0; "><p style="margin:0;">Footer</p></div></div>

Das muss man nach dem oben Gesagten nicht mehr erläutern. Das Ergebnis sieht wie folgt aus:

Testbeispiel mit gefloateten DIvs und gekoppelter vertikaler Ausdehnung

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

yellow_bryce

Im dargestellten Beispiel bestimmt nun der zur Laufzeit längere der beiden Inhalte der gefloateten DIVs die Höhenskalierung der Seite und die Höhe der eingesetzten Hintergründe (ggf. mit Bildern).

Wir haben nun eine Lösung, die alle unsere Anforderungen erfüllt, und zudem haben wir eine sehr flexible Art gefunden, den Hintergrund gefloateter Bereiche dynamisch vom Inhalt innerer DIVs abhängig zu machen. Ohne Javascript !

Ferner bleibt die Erkenntnis, dass man die Höhe optisch entkoppelter Bereiche sehr wohl auch erst zur Laufzeit durch einen dynamisch erzeugten Inhalt festlegen und synchronisieren kann.

Viel Spaß weiterhin mit den Möglichkeiten von CSS2!