Webkrauts Logo

Webkrauts Webkrauts Schriftzug

- für mehr Qualität im Web

Ablösung für Float-Layouts

CSS3 Flexbox

Ablösung für Float-Layouts

Mehrspaltige Designs setzen Webworker heutzutage mit Floats um. Das mag sich in Zukunft ändern. Denn mit dem CSS3-Modul Flexbox steht eine nützliche Alternative in den Startlöchern. HTML-Elemente können damit spalten- oder zeilenweise angezeigt werden, die Reihenfolge der Elemente lässt sich steuern und Breiten oder Höhen passen sich automatisch an.

Anhand des CSS3-Flexbox-Moduls wird deutlich, wie dynamisch der W3C-Standard ist. Wo einerseits CSS-Eigenschaften wie box-shadow oder border-radius mittlerweile ohne Vendor-Präfix (z.B. -moz-, -webkit-) verwendet werden können, hat die Browser-Implementierung von flex-Eigenschaften gerade erst begonnen.

Der erste Entwurf des Flex-Moduls vom W3C stammt aus 2009, was im Vergleich zu anderen Modulen sehr jung ist. Trotzdem hat das Flex-Modul seit September 2012 den Status »Candidate Recommendation« – was so viel bedeutet, dass es keine tiefergehenden Änderungen mehr geben wird. Vom Entwurf bis zum jetzigen Stand hat sich das Modul mehrfach stark verändert, was den Umfang, vor allem aber die Bezeichnungen der CSS-Eigenschaften betrifft. Im Web sind Beispiele für Firefox zu finden, die mit -moz-box-flex arbeiten, oder für den Internet Explorer, die -ms-flexbox als Bezeichner verwenden.

Dieser Beitrag beschäftigt sich jedoch nicht mit dem, was in der Vergangenheit ausprobiert wurde, sondern soll einen allgemeinen Überblick verschaffen, welche Möglichkeiten Flexbox in Zukunft bieten wird. flex-Eigenschaften werden aktuell von Opera (ab der Version 12.10) sowie von Google Chrome (ab der Version 21.0) mit dem Vendor-Präfix -webkit- unterstützt (mobile Browser sind in diesem Beitrag nicht berücksichtigt). Von daher wird in den CSS-Beispielen die Schreibweise für den Chrome sowie die Standardschreibweise gezeigt. Die Demo-Quelltexte findet ihr am Ende des Beitrags.

Was macht Flexbox?

Vereinfacht gesagt lassen sich in einer Flexbox Elemente in Reihen oder Spalten anzeigen. HTML-Elemente passen sich je nach Deklaration dem verfügbaren Platz an und können unterschiedlich ausgerichtet werden. Auch die Reihenfolge innerhalb der Reihen und Spalten ist individuell veränderbar.

Die Grundlage für die folgenden Beispiele stellt ein einfaches HTML-Konstrukt dar, welches das Grundgerüst jeder Webseite sein könnte. Die Beispiele sind in den Quelltexten fortlaufend zu finden, das x in der id="beispiel-x" ist dabei durch die jeweilige Beispielnummer ersetzt.

  1. <div id="beispiel-x">
  2.   <nav>Navigation</nav>
  3.   <section>Inhalt</section>
  4.   <aside>Weiteres</aside>
  5. </div>

Über CSS wird für jedes Element eine eigene Hintergrundfarbe, zusätzlich Rahmen und runde Ecken für alle Elemente vergeben. Dies hat noch nicht mit dem Flexbox-Modul zu tun, sondern dient lediglich der Anschaulichkeit:

Die drei Boxen nehmen die ganze Breite ein und werden untereinander dargestellt
Abbildung 1: Darstellung des einfachen HTML-Codes

Grundlage für die flex-Darstellung

Die CSS-Eigenschaft display hat mit CSS3 zwei neue Parameter bekommen: flex und inline-flex. Eine dieser Eigenschaften muss dem umgebenden div zugewiesen werden, was die Flexbox-Darstellung »aktiviert«. Hier, wie in allen folgenden Beispielen, wird neben der Standardschreibweise die Eigenschaft mit dem Vendor-Präfix -webkit- eingesetzt, damit Google Chrome diese erkennt. Safari unterstützt die Eigenschaften jedoch nicht, auch wenn dies ein Webkit-Browser ist.

  1. #beispiel-01 {
  2.   display: -webkit-flex;
  3.   display: flex;
  4. }
Drei Boxen nebeneinander dargestellt, jeweils so breit wie der Inhalt
Abbildung 2: Darstellung mit display: flex

Dies erinnert zuerst an die Darstellung per float: left. Allerdings, und dies ist der große Vorteil gegenüber float: nachfolgende Elemente sind von display: flex nicht betroffen und umfließen die Flexbox nicht. Vergleichbares wie ein clear: both ist nicht notwendig.

Dass sich die einzelnen HTML-Elemente nun nebeneinander anordnen, liegt daran, dass mit dem Setzen von display: flex automatisch die CSS-Eigenschaft flex-direction greift. Diese hat den Standard-Parameter row. Würdest du die Eigenschaft flex-direction explizit hinterlegen, sähe die vollständige CSS-Regel wie folgt aus:

  1. #beispiel-01 {
  2.   display: -webkit-flex;
  3.   display: flex;
  4.   -webkit-flex-direction: row; /* Standard */
  5.   flex-direction: row; /* Standard */
  6. }

Alternativ kannst du flex-direction: column vergeben, allerdings werden dann die drei HTML-Element in einer Spalte angezeigt; die Browserdarstellung entspricht somit Abbildung 1.

Angabe einer relativen Basis-Breite

Die flex-Eigenschaften werden eigentlich erst dann spannend, wenn Breiten eingesetzt werden:

  1. #beispiel-02 nav,
  2. #beispiel-02 aside {
  3.   -webkit-flex-basis: 20%;
  4.   flex-basis: 20%;
  5. }
  6.  
  7. #beispiel-02 section {
  8.     -webkit-flex-basis: 60%;
  9.     flex-basis: 60%;
  10. }

Mit diesen CSS-Regeln werden die Navigation und das aside-Element auf 20% gesetzt. Der Inhaltsbereich wird mit einer Breite von 60% versehen. Solch ein Laoyut würden wir heutzutage mit floatenden divs realisieren (bzw., so was wurde früher gerne über ein Tabellen-Layout umgesetzt). Die Darstellung nimmt nun die ganze Breite ein:

Drei Boxen nebeneinander dargestellt, nehmen zusammen die verfügbare Breite ein
Abbildung 3: Automatische Verteilung der einzelnen Blöcke nach Einsatz von flex-basis.

Allerdings stellt flex-basis keine definitive Breite oder Höhe dar, sondern dient als relative Grundeinheit, nach dem sich die einzelnen Elemente proportional innerhalb der Flexbox anpassen. Ist die Summe der Ausmaße geringer als die Breite bzw. Höhe der umgebenen Box, wird auch nur dieser Platz eingenommen. Wobei in der Breite ohne weitere Angaben 100% der verfügbaren Breite relevant ist, in der Höhe muss die Flexbox mit einer bestimmten Höhe versehen sein, damit sich die Elemente verhältnismäßig anpassen. Wenn hingegen die Summe aller Breiten bzw. Höhen mehr als 100% ergeben, oder feste Pixel-Werte vergeben werden, die zusammen addiert mehr als die Dimension der Flexbox einnehmen, passen sich die in der Flexbox liegenden Elemente automatisch an den verfügbaren Platz an:

  1. #beispiel-03 section {
  2.   -webkit-flex-basis: 120%;
  3.   flex-basis: 120%;
  4. }
Drei Boxen nebeneinander und auf die ganze Breite verteilt dargestellt, hier die mittlere Box breiter als in Abbildung 3
Abbildung 4: Flex-Elemente passen sich automatisch an den verfügbaren Platz an, auch wenn sie mehr als 100% in der Eigenschaft flex-basis aufweisen.

Der große Vorteil eines Flex-Layouts wird in Abbildung 4 deutlich. Selbst wenn ein flex-basis-Wert zu hoch vergeben wird, sortieren sich die Elemente trotzdem automatisch an, lediglich mit andern Breitenverhältnissen. Dies unterscheidet sich wesentlich von einem floatenden div-Layout, bei dem eine zu hohe Breite, oder aber auch margin- oder padding-Werte dazu führen, dass Elemente in die nächste Reihe rutschen, wenn die verfügbare Gesamtbreite überschritten ist.

Automatische Höhenanpassung der Blöcke

Der nächste Schritt zeigt das, was eigentlich jeder Frontend-Entwickler schon immer wollte: drei Elemente nebeneinander, unabhängig vom Inhalt auf die gleiche Höhe zu bringen. Genaugenommen ist dies ja der Grund, warum früher jahrelang Tabellenlayouts genutzt wurden, da diese als einziger Weg erschienen, ein mehrspaltiges Layout zu entwickeln, bei dem alle Spalten gleich hoch sind. Diesen Effekt bei einem floatendem div-Layout zuverlässig zu erzielen, war bislang nur mit verschiedenen Workarounds möglich, wie durch den geschickten Einsatz von Hintergrundgrafiken oder auch der Anpassung der Höhen über JavaScript. Flexbox »erledigt« dies mit nur einer Eigenschaft:

  1. #beispiel-04 {
  2.   display: -webkit-flex;
  3.   display: flex;
  4.   -webkit-align-items: stretch;
  5.   align-items: stretch;
  6. }

align-items hat den Standardwert stretch und müsste hier nicht gesetzt werden. Auch ohne diese explizit gesetzte Eigenschaft werden alle Flexbox-Elemente auf die gleiche Höhe gestreckt. Alleine die Höhenangabe reicht aus, auch wenn sie nur für ein Element in einer Reihe vergeben ist, damit alle Elemente die gleiche Höhe annehmen.

  1. #beispiel-04 section {
  2.   min-height: 150px;
  3. }

Die CSS-Regel setzt lediglich den Inhaltsblock auf mindestens 150px, Navigation und aside-Element haben keine zusätzliche Deklaration:

Drei Boxen nebeneinander, nehmen alle die gleiche Höhe von 150px ein
Abbildung 5: Boxen strecken sich standardmäßig auf die gleiche Höhe.

Für align-items können andere Werte vergeben werden, welche die Anordnung der Boxen auf der Y-Achse festlegt. In den folgenden Beispielen sind die Parameter flex-start, flex-end und center gezeigt:

Drei Boxen nebeneinander, die mittlere ist 150px hoch, alle Boxen sind an der Oberkante ausgerichtet
Abbildung 6: align-items: flex-start
Drei Boxen nebeneinander, die mittlere ist 150px hoch, alle Boxen sind auf der Y-Achse zentriert
Abbildung 7: align-items: center
Drei Boxen nebeneinander, die mittlere ist 150px hoch, alle Boxen sind am Unterrand ausgerichtet
Abbildung 8: align-items: flex-end

Spätestens jetzt wird das Potential der Flexbox deutlich. Sie bietet einerseits das float-Verhalten und sortiert Boxen nebeneinander, ohne aber die unerwünschten Nebeneffekte von float zu haben. Zusätzlich stehen Möglichkeiten der horizontalen Ausrichtung zur Verfügung, wie bislang nur über Tabellen, ggf. geschickter Positionierung oder über Workarounds mit JavaScript zu realisieren war.

Verändern der Reihenfolge

Das Flexbox-Modul bietet noch mehr. Über einen anderen Parameter für flex-direction kann die Reihenfolge der Blöcke umgedreht werden:

  1. #beispiel-05 {
  2.   -webkit-flex-direction: row-reverse;
  3.   flex-direction: row-reverse;
  4. }
Drei Boxen nebeneinander, die erste Box im Quelltext wird rechts, die letzte Box im Quelltext wird links angezeigt
Abbildung 9: Umgekehrte Reihenfolge der Blöcke per row-reverse

Nicht nur die Umkehrung der Blöcke von links nach rechts ist möglich, auch von oben nach unten. Dazu dient der Wert column-reverse für die CSS-Eigenschaft flex-direction.

  1. #beispiel-06 {
  2.   -webkit-flex-direction: column-reverse;
  3.   flex-direction: column-reverse;
  4. }
Drei Boxen untereinander, in umgekehrter Reihenfolge wie im Quelltext angezeigt
Abbildung 10: Umgekehrte Reihenfolge innerhalb einer Spalte per flex-direction: column-reverse

In Abbildung 10 wird nicht nur deutlich, dass die Blöcke von unten nach oben dargestellt werden. Ebenfalls ist hier zu erkennen, wie sich die oben vergebene Höhe für das section-Element auswirkt: Boxen werden auf eine Höhe gestreckt, wenn sie innerhalb einer Reihe angezeigt werden. Werden mehrere Boxen in mehreren Reihen angezeigt, haben die Höhen in verschiedenen Reihen keinen Einfluss aufeinander.

Aber nicht nur das Umdrehen der Boxen ist möglich. Auch die konkrete Reihenfolge kann über die neue CSS-Eigenschaft order gesteuert werden:

  1. #beispiel-07 nav {
  2.   -webkit-order: 3;
  3.   order: 3;
  4. }
  5.  
  6. #beispiel-07 section {
  7.   -webkit-order: 1;
  8.   order: 1;
  9. }
  10.  
  11. #beispiel-07 aside {
  12.   -webkit-order: 2;
  13.   order: 2;
  14. }

Dabei wird über diese CSS-Regeln und über die Eigenschaft order jedem einzelnem Element innerhalb der Flexbox eine bestimmte Position zugewiesen. Sollte die Reihenfolge durch column-reverse oder row-reverse grundsätzlich verdreht sein, greift auch die eigens gesetzte Reihenfolge umgekehrt. Oben definierte CSS-Regeln wirken sich wie folgt aus:

Drei Boxen nebeneinander, die erste Box im Quelltext wird rechts, die zweite links und die dritte wird in der Mitte angezeigt
Abbildung 11: Per order kann die Reihenfolge der Elemente in der Flexbox konkret angegeben werden.

Umbruch von Elementen in einer Flexbox

Oben wurde über flex-basis die Basis-Breite für die einzelnen Elemente angegeben, was dazu führte, dass sich die Boxen automatisch auf die verfügbare Breite verteilten. Anders verhalten sich Elemente in einer Flexbox, wenn sie mit einer festen Breite per width oder min-width versehen sind. Zur Verdeutlichung wird der HTML-Code um zwei div-Elemente erweitert:

  1. <div id="beispiel-08">
  2.   <nav>Navigation</nav>
  3.   <section>Inhalt</section>
  4.   <aside>Weiteres</aside>  
  5.   <div class="box-4">Box 4</div>  
  6.   <div class="box-5">Box 5</div>
  7. </div>

Alle Elemente in der Flexbox werden im nächsten Schritt mit einer festen Breite versehen:

  1. #beispiel-08 nav,
  2. #beispiel-08 aside,
  3. #beispiel-08 section,
  4. #beispiel-08 div {
  5.   width: 150px;
  6.   min-height: 100px;
  7. }
Fünf Boxen nebeneinander, die rechts vom Browserfenster nicht angezeigt wird. Die vierte wird nur teilweise, die fünfte gar nicht angezeigt
Abbildung 12: Elemente mit fester Breite fließen über die umgebene Flexbox (hier über die Größe des Browserfensters) hinaus.

Dieses Verhalten in Abbildung 12 erinnert daran, wenn ein overflow: hidden gesetzt sei. Schlechter als beim float, brechen die Elemente nicht in die nächste Reihe um, sondern fließen aus dem Layout heraus.

Für diesen Fall bietet das Flexbox-Modell eine weitere Eigenschaft: flex-wrap mit dem Parameter wrap. Standardwert für flex-wrap ist nowrap und dafür verantwortlich, dass die einzelnen Elemente innerhalb der Flexbox nicht umgebrochen werden und, wie in der Abbildung 12, über die Dimensionen der Flexbox hinaus laufen.

  1. #beispiel-09 {
  2.   -webkit-flex-wrap: wrap;
  3.   flex-wrap: wrap;
  4. }
Fünf Boxen nebeneinander, die vierte und fünfte brechen in eine zweite Reihe um
Abbildung 13: Per flex-wrap: wrap brechen Elemente in eine neue Reihe um

Ausdehnen von Elementen mit fester Breite

Zusätzlich kann das Ausdehnungsverhalten von Elementen in Flexboxen verändert werden. Die Eigenschaft flex-grow beeinflusst, dass auch Boxen mit festen Breiten gedehnt werden. Hier sich nummerische Werte möglich. Sind zwei Boxen in einer Flexbox, eine davon mit dem Wert flex-grow: 1, die andere mit dem Wert flex-grow: 5, dann nimmt letztere Box mehr Raum als die erste ein.

  1. #beispiel-10 nav,
  2. #beispiel-10 aside,
  3. #beispiel-10 section,
  4. #beispiel-10 div {
  5.   width: 150px;
  6.   -webkit-flex-grow: 1;
  7.   flex-grow: 1;
  8.   -webkit-flex-basis: auto;
  9.   flex-basis: auto;
  10. }

In diesem Beispiel werden alle fünf Boxen mit flex-grow: 1 versehen, was dazu führt, dass sich alle Boxen im Verhältnis gleich vergrößern. Zusätzlich wird noch eine weitere Eigenschaft benötigt: flex-basis: auto. Das auto für flex-basis sorgt dafür, dass sich die Boxen auf die volle Breite ausdehnen.

Fünf Boxen nebeneinander, drei in der ersten Reihe, zwei in der zweiten Reihe, wobei die Boxen in einer Reihe jeweils die ganze verfügbare Breite einnehmen
Abbildung 14: Per flex-grow: 1 und flex-basis: auto werden die einzelnen Boxen auf die ganze Breite gestreckt ndash; und dies jeweils pro Reihe.

Responsive Design und Flexbox

Genau genommen ist das letzte Beispiel vor allem für Responsive Design relevant, soll aber hervorheben, wie einfach Flexbox mit der @media-Regel kombiniert werden kann. Grundlage hierfür ist das Beispiel 4, das in Abbildung 5 zu sehen ist. Die Darstellung einschließlich Browserfenster sieht wie folgt aus:

Drei Boxen nebeneinander im Kontext des Browserfensters
Abbildung 15: Bei normaler Breite greift in der Flexbox die reihenweise Darstellung der einzelnen Elemente.

Zusätzlich wird ein Media-Query definiert:

  1. @media all and (max-width: 500px) {
  2.   #beispiel-11 {
  3.     -webkit-flex-direction: column;
  4.     flex-direction: column;
  5.   }
  6. }

Diese Regel sorgt dafür, dass unter einer Fensterbreite von 500px die Darstellung in der Flexbox von der reihenweisen Darstellung (row) auf die spaltenweise Darstellung (column) umschaltet. Die Darstellung desselben HTML-Codes sieht dann wie folgt aus:

Das Browserfenster ist schmaler als in Abbildung 15. Hier werden die Boxen untereinander angezeigt
Abbildung 16: Bei geringer Fensterbreite springt das Layout zu einer spaltenweisen Darstellung um.

Fazit

Das Flexbox-Modul des CSS3-Standards bietet vielfältige Möglichkeiten, welche die Eigenschaften von fließenden Boxen per float mit den Verhalten von Tabellen kombiniert, zusätzlich aber noch weitere Steuerungsmöglichkeiten der Elemente innerhalb einer Flexbox ermöglicht.

Langfristig können so einfach stabile Layouts aufgebaut werden. Ab wann das genau der Fall sein wird, ist heute nicht eindeutig zu sagen. Firefox hat die Implementierung des Flex-Moduls für die Version 18 angekündigt (erscheint im Januar 2013); vor allem wird es aber vom Internet Explorer abhängen, wann flex-Eigenschaften browserübergreifend eingesetzt werden können. Behält Microsoft die Veröffentlichungzyklen seines Browsers bei, ist der Internet Explorer 11 in den nächsten ein bis drei Jahren zu erwarten. Inwiefern dieser das Flex-Modul implementiert sein wird, ist heute nicht abzusehen.

Weiterführende Links

Kommentare

Sören Hentzschel
am 11.12.2012 - 10:55

Danke für den Artikel, der war wirklich sehr gut zu lesen! :)

Kleine Korrektur: Mozilla plant den flexbox-Support offziell für Firefox 20:
http://blog.dholbert.org/2012/12/css3-flexbox-enabled-in-nightlies-ready...

Permanenter Link

Christian
am 11.12.2012 - 13:17

Wieder ein sehr gelungener Artikel. Vielen Dank.

Permanenter Link
Olaf Gleba

Olaf Gleba (Webkraut)
am 11.12.2012 - 14:15

Sehr schöner Artikel, danke. Und kommt zur richtigen (Weihnachts)Zeit, wo man ja den ein oder anderen Wunsch im Kopf spazieren führt. Auch wenn sich das wohl eher auf Weihnachten 2013 bezieht. Aber Vorfreude ist ja feines.

Auch wenn floats als Layout-Krücke etabliert sind, bin ich gerade recht begeistert, was mit display: inline-block alles möglich ist. Auch eine Krücke, ja, aber mit weniger Nebenwirkung und Möglichkeiten, die floats nicht bieten.

Permanenter Link

Alex
am 11.12.2012 - 14:37

DANKE! Auch für Hobby-Webbastler sehr verständlich und anschaulich geschrieben.

Permanenter Link

Aaron
am 11.12.2012 - 14:39

Danke für den Überblick! Flexbox wird das Bauen von Layouts einiges praktischer machen.

Permanenter Link

Paul
am 11.12.2012 - 21:17

Hmm, schon spannend, aber gab es nicht auch einmal einen Ansatz, der versucht klassische Layoutmanager im Standard zu integrieren. Fänd ich persönlich sinnvoller! Aber ich bin ja kein Webexperte..

Permanenter Link
Stephan Heller

Stephan Heller (Autor)
am 12.12.2012 - 11:19

Hallo Zusammen,
vielen Dank für das Feedback - ja, Flexbox ist noch Zukunftsmusik - und auch nur eine von vielen neuen Möglichkeiten.
Spannend ist es allemale, man darf wirklich gespannt sein, was sich durchsetzten wird.
Viele Grüße, Stephan

Permanenter Link

Mo
am 17.12.2012 - 09:49

Es gibt einen Polyfill für Flexbox: Flexie (https://github.com/doctyper/flexie)

Permanenter Link

Harry
am 21.12.2012 - 20:41

Danke für die interessante Darlegung.
Ich werde es im Hinterkopf behalten und bei Gelegenheit auch mal selbst ein wenig in diese Richtung testen. Allerdings solange die Sache noch nicht browserübergreifend eingesetzt werden kann, wird es (bei mir) wohl über die Testphase nicht hinausgehen.

Permanenter Link

Die Kommentare sind geschlossen.