CSS kompakt: Einschließen (Clearing) von Floats

Mehrspaltenlayout mit float

Die Eigenschaft float gehört zu den wichtigsten CSS-Eigenschaften zur Umsetzung von flexiblem Mehrspaltenlayout. Da sie aber nie zu diesem Zweck erfunden wurde, sondern eher dafür zweckentfremdet wird, sind einige Tricks und Kniffe notwendig, um zu einem klassischen Mehrspaltenlayout zu kommen.

Bereits 2006 habe ich einen ausführlichen Artikel zu CSS-Spaltenlayout verfasst. Da immer noch Unklarheiten zum Thema herrschen, will ich es noch einmal kompakt »von oben nach unten«, von der Theorie zur Praxis hin zusammenfassen.

Beispielsweise sorgt float: left erst einmal nur dafür, dass darauffolgende Elementboxen rechts um die Box des Elements »herumfließen«. Der folgende Inhalt lässt sich in ein Element fassen, das z.B. mit margin-left (linker Außenrand) eingerückt wird. So entsteht erst der Eindruck von zwei Spalten. (Grob verkürzt, es gibt noch andere Methoden und weiteres zu beachten.)

Spalte 1
Links floatendes Element

Spalte 2
Folge-Element im normalen Fluss

Problemstellung und 2+1 Lösungsansätze

Nun besteht oftmals der Wunsch, dass ein Container-Element beide Spalten umfasst. Die Höhe soll sich nach dem Inhalt beider Spalten richten. Das Element mit float: left - floatendes Element oder schlicht »Float« genannt - beeinflusst die Höhe des Container-Elements allerdings nicht. Wenn sie die andere Spalte in der Höhe überragt, dann lappt sie aus dem Container-Box heraus:

Spalte 1
Links floatendes Element mit viel mehr Inhalt. Ragt heraus!

Spalte 2
Folge-Element im normalen Fluss

Damit das Container-Element seine Höhe entsprechend anpasst, ist ein Einschließen des Floats nötig.

Es gibt im Grunde zwei standardkonforme Ansätze, floatende Element mit beliebiger, flexibler Höhe einzuschließen:

  1. Das Erzeugen eines Block Formatting Contexts (Abkürzung: BFC)
  2. Das Einfügen eines Elements mit clear am Ende des Container-Elements, üblicherweise Clearfix genannt

Es gibt jeweils verschiedene Methoden, um einen BFC zu erzeugen und einen Clearfix umzusetzen. Alle Spielarten gehen jedoch auf diese Grundansätze zurück.

Für den Internet Explorer 5-7 kommt ein dritter, proprietärer Ansatz hinzu: hasLayout. Der IE vor Version 8 unterstützt nur diesen Ansatz, ab IE 8 können die oben genannten verwendet werden. Es gibt wiederum verschiedene Möglichkeiten, um hasLayout zu triggern.

Block Formatting Context (BFC)

Ein BFC ist ein CSS-internes Konzept, das Browser zum Layouten der Elementboxen heranziehen. Eine Elementbox kann einen neuen BFC erzeugen und damit bekommt die Box besondere Eigenschaften. Drei der wichtigsten sind:

  1. Ein BFC erzeugt einen neuen Float-Kontext. Ein Element mit clear: left/right/both wird nicht unter allen Floats im Dokument dargestellt, sondern »cleart« nur diejenigen, die sich im selben BFC befinden.
  2. Ein BFC überlappt sich nicht mit Floats. Normalerweise liegen Elemente »hinter« den Floats und lediglich der Elementinhalt (z.B. Text) wird neben das Float verschoben. Bei einem BFC gibt es keine solche Überlappung, bei der das Float über dem nicht-floatenden Folgeelement liegt. Beide Boxen werden wirklich nebeneinander gelayoutet.
  3. Last but not least: Ein BFC schließt alle floatenden Kindelemente ein, seine Höhe passt sich entsprechend an.

Das Wissen um BFCs ist essentiell bei fortgeschrittenem CSS-Layout. All diese Eigenschaften kann man sich in verschiedenen Fällen zu Nutze machen.

BFC-Auslöser

Es lässt sich nicht direkt einstellen, dass eine Elementbox die BFC-Eigenschaften erhält. Es gibt jedoch verschiedene CSS-Eigenschaften, die implizit einen BFC auslösen. Als da wären:

  1. float mit einem anderen Wert als none, sprich left oder right
  2. overflow mit einem anderen Wert als visible, sprich hidden, scroll oder auto

Es gibt noch weitere Eigenschaften, die ich hier der Einfachheit verschweige, da sie nicht so universell für Container-Elemente zum Einschließen von Floats eignen. Siehe dazu CSS 101: Block Formatting Contexts und Block Formatting Contexts im CSS-2.1-Standard.

Floats einschließen mit BFC

Das Einschließen von Floats mittels float als BFC-Auslöser erfordert ein zusätzliches width: 100%, damit die Box nicht auf die Inhaltsbreite zusammenschrumpft (»shrink-fit«), sondern weiterhin die ganze Breite umspannt. Damit ist gewährleistet, dass neben diesem Float kein Inhalt vorbeifließt. Schließlich wollen wir keinen echten Float, sondern nur BFC auslösen, um die Floats im Container einzuschließen.

Verbreiteter ist der BFC-Auslöser overflow: hidden. Dies ist eine etablierte Technik zum Einschließen von Floats. Beispielsweise verwendet das CSS-Framework YAML overflow: hidden zum Einschließen von Floats innerhalb der verschachtelter Mehrspaltigkeit. (Der Vollständigkeit halber: YAML verwendet an anderen Stellen auch das oben beschriebene float sowie den unten beschriebenen Clearfix.)

Spalte 1
Links floatendes Element mit viel mehr Inhalt

Spalte 2
Folge-Element im normalen Fluss

Probleme von overflow: hidden

Es darf jedoch nicht die Hauptwirkung von overflow: hidden übersehen werden: Inhalte werden abgeschnitten. Beim CSS-Spaltenlayout wirkt sich diese u.a. negativ aus, immer wenn bestimmte Inhalte den Rändern zu nahe kommen oder bewusst über sie hinausragen:

  1. Bei der Fokussierung z.B. von Links wird der Rahmen (outline) abgeschnitten, mit dem das Browser das Element hervorhebt.
  2. Dasselbe gilt für Box- und Text-Schatten (box-shadow, text-shadow) von Elementen an den Container-Rändern.
  3. Beim Sub-Pixel-Rendering von Schrift sind standardmäßig auch Pixel außerhalb des Containers betroffen. overflow: hidden verhindert zumindest in einigen Browsern das korrekte Schrift-Rendering.
  4. Der Einsatz von position: absolute sowie position: relative bei Elementen im Container wird eingeschränkt, denn an den Containergrenzen wird rigoros abgeschnitten.

overflow: hidden ist damit zwar eine sehr einfache und elegante, aber nicht unproblematische Lösung zum Einschließen von Floats. Nachdem ich overflow: hidden als BFC-Auslöser lange auf breiter Basis eingesetzt habe, haben mir u.a. die obigen Nachteile im Praxiseinsatz zu schaffen gemacht, sodass ich mittlerweile wieder eher zum Clearfix tendiere.

Clearfix

Der Clearfix ist ein unsichtbares, leeres Element, das eine 0 Pixel hohe Box erzeugt, welche clear: both besitzt. Dieses Element wird am Ende des Container-Elements eingefügt, ist also sein letztes Kindelement. Durch das Clearing wird das Container-Element in der Höhe so vergrößert, dass es alle Floats im jeweiligen Float-Kontext einschließt.

Spalte 1
Links floatendes Element mit viel mehr Inhalt

Spalte 2
Folge-Element im normalen Fluss

Clear-Element, hier sichtbar zur Demonstration

Früher hat man zu diesem Zweck unzählige

in den HTML-Code eingefügt. Heute ist Konsens, dass diese Darstellungsinformation im HTML nichts zu suchen hat (»Separation of Concerns«) und es dort die Wartbarkeit verschlechtern würde. Um die Trennung von Inhalt und Präsentation zu wahren, wird die Clear-Box stattdessen mit CSS eingefügt.

Das geht mittels CSS-erzeugtem Inhalt. Damit lassen sich CSS-Boxen samt Textinhalt einfügen und direkt via CSS formatieren. Diese Boxen tauchen nicht im DOM auf, werden jedoch gerendert und beeinflussen das CSS-Layouting. Inhalte werden mit einer Kombination aus dem Pseudoelement :after (CSS-3-konforme Syntax: ::after) und der Eigenschaft content eingefügt:

#container:after {
   display: block;
   clear: both;
   content: "Per CSS eingefügte Clear-Box";
}

Demonstration:

Spalte 1
Links floatendes Element mit viel mehr Inhalt

Spalte 2
Folge-Element im normalen Fluss

Damit diese eingefügte Box nicht sichtbar ist, sondern nur das Clearing anwendet, bekommt sie üblicherweise noch weitere Eigenschaften wie height: 0, visibility: hidden und falls nötig font-size: 0. Vollständig sieht der Clearfix-Code dann so aus:

#container:after {
   display: block;
   clear: both;
   content: ".";
   height: 0;
   visibility: hidden;
}

Nachteile der gängigen Praxis class="clearfix"

Im Gegensatz zum Einschließen mittels overflow: hidden (BFC) kann der »Clearfix« nicht so einfach im Stylesheet wiederholt werden – der CSS-Code würde sehr schnell redundant werden. Es ist daher gängig, allen Elementen, die ihre floatenden Kindelemente einschließen sollen, eine Klasse clearfix zu geben, sodass der CSS-Code für den Clearfix nur einmal im Stylesheet stehen muss. Der gravierende Nachteil ist, dass damit die Trennung von Inhalt und Präsentation aufgeweicht wird. Mit class="clearfix" werden wieder massenhaft präsentationsbezogene Informationen im HTML untergebracht. Ob ein Element Floats einschließt, ist damit nicht aus der CSS-Formatierung im Stylesheet ersichtlich, sondern die Formatierungsregeln sind in HTML und CSS verstreut.

hasLayout (IE < 8)

hasLayout ist ein Thema für sich. hasLayout ist internes Konzept bei der CSS-Umsetzung im Internet Explorer 5-7 und der Schlüssel zum IE-kompatiblen CSS-Layout. hasLayout bezeichnet eine Eigenschaft von Boxen, eine Box »hat Layout«. hasLayout entspricht in verschiedener Hinsicht dem BFC in standardkonformen Browsern: Elemente mit hasLayout schließen Floats automatisch ein, überlappen sich nicht mit Floats und erzeugen einen neuen Float-Kontext. Dies sind aber nur einige Auswirkungen unter vielen – für uns ist hier nur interessant, dass hasLayout das Mittel der Wahl zum Einschließen von Floats in älteren IEs ist.

hasLayout-Auslöser

Es gibt verschiedene CSS-Eigenschaftswerte, die hasLayout beim formatierten Element auslösen. Die wichtigsten sind:

  • Feste Angaben für Breite oder Höhe (width, height). Beim häufig verwendeten height: 1% ignoriert der IE die Höhenangabe, gibt dem Element jedoch »Layout«
  • float ist ebenfalls ein hasLayout-Auslöser (mit einem anderen Wert als none, versteht sich)
  • Empfohlener hasLayout-Auslöser ist zoom: 1. zoom ist eine Microsoft-proprietäre CSS-Eigenschaft, die im Falle des Wertes 1 (= 100% Zoom) keine andere Auswirkung hat, als dass das Element »Layout« bekommt.

zoom: 1 kann in Extra-Stylesheets untergebracht werden, die per Conditional Comments nur für den IE < 8 eingebunden werden. Es ist aber auch harmlos, zoom: 1 direkt ins Hauptstylesheet zu schreiben. Standardkonforme Browser ignorieren die Angabe einfach. Das macht das Stylesheet allerdings invalide. Manche Webautoren ziehen die Integration des kleinen IE-Fixes in das Originalstylesheet der Validität vor.

Floats einschließen browserübergreifend mit BFC und hasLayout geht demnach so:

#container { overflow: hidden; zoom: 1; }

Neben dem Einschließen von Floats hat zoom: 1 wie gesagt schwerwiegende Auswirkungen - um diese zu verstehen, ist ein Studium der genannten Literatur zu hasLayout nötig.

Unterschiede zwischen BFC, Clearfix und hasLayout

Keine der Methoden ist bedenkenlos einsetzbar und ohne Nebenwirkungen. Die Ansätze sind sehr unterschiedlich:

  • Ein BFC hat besondere Eigenschaften, er erzeugt einen neuen Float-Kontext und verhindert das Überlappen mit Floats. Das kann gewünscht sein oder auch nicht. overflow: hidden hat ferner schwerwiegende Risiken – und wird dennoch breit und erfolgreich eingesetzt.
  • Der Clearfix ist ein ganz anderer Ansatz, der voraussetzt, dass an der jeweiligen Stelle bedenkenlos clear verwendet werden kann. Ansonsten ist er relativ sicher und robust, kann aber nicht so flexibel angewendet werden wie ein simples overflow: hidden.

    Im Gegenzug eignet sich der Clearfix für weitere Effekte wie den der gleich langen Spalten, siehe Kombinationslösung in meinem ausführlichen Artikel sowie Das Clearing der Spalte #col3 in der YAML-Dokumentation.

  • Für den IE < 8 bleibt nur hasLayout. Und hasLayout ist ein Minenfeld. Es geht leider nicht ohne – und mit nur unter Schmerzen. Nach einiger Zeit bekommt man jedoch Übung im gezielten hasLayout-Einsatz.

Historische Quellen zum Einschließen von Floats

2004-05-14
How To Clear Floats Without Structural Markup von Tony Aslett, John Gallant (Position Is Everything)
2005-02-26
Simple Clearing of Floats von Paul O’Brien, Alex Walker
2005-06-30
On having layout — the concept of hasLayout in IE/Win von Ingo Chao u.a.
2007-05-09
Über hasLayout — das Konzept des hasLayout im IE/Win. Deutsche Übersetzung von Corina Rudel
2009-12-06
»The New Clearfix Method«. Aktualisierung der Aslett/PIE-Methode durch Jeff Starr (IE/Mac fällt heraus und weitere kleine Anpassungen)

Alternativen zu Float-Layouts

Bei soviel Ärger um Floats sei wie auch schon 2006 auf alternative Layouttechniken hingewiesen:

Eine Diskussion möglicher Zukunftstechniken leistet Stephen Hay in seinem Vortrag The Future State of Layout. Vorgestellt werden: