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.
- <div id="beispiel-x">
- <nav>Navigation</nav>
- <section>Inhalt</section>
- <aside>Weiteres</aside>
- </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:
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.
- #beispiel-01 {
- display: -webkit-flex;
- 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:
- #beispiel-01 {
- display: -webkit-flex;
- display: flex;
- -webkit-flex-direction: row; /* Standard */
- flex-direction: row; /* Standard */
- }
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:
- #beispiel-02 nav,
- #beispiel-02 aside {
- -webkit-flex-basis: 20%;
- flex-basis: 20%;
- }
- #beispiel-02 section {
- -webkit-flex-basis: 60%;
- flex-basis: 60%;
- }
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:
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:
- #beispiel-03 section {
- -webkit-flex-basis: 120%;
- flex-basis: 120%;
- }
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:
- #beispiel-04 {
- display: -webkit-flex;
- display: flex;
- -webkit-align-items: stretch;
- align-items: stretch;
- }
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.
- #beispiel-04 section {
- min-height: 150px;
- }
Die CSS-Regel setzt lediglich den Inhaltsblock auf mindestens 150px, Navigation und aside
-Element haben keine zusätzliche Deklaration:
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:
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:
- #beispiel-05 {
- -webkit-flex-direction: row-reverse;
- flex-direction: 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
.
- #beispiel-06 {
- -webkit-flex-direction: column-reverse;
- 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:
- #beispiel-07 nav {
- -webkit-order: 3;
- order: 3;
- }
- #beispiel-07 section {
- -webkit-order: 1;
- order: 1;
- }
- #beispiel-07 aside {
- -webkit-order: 2;
- order: 2;
- }
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:
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:
- <div id="beispiel-08">
- <nav>Navigation</nav>
- <section>Inhalt</section>
- <aside>Weiteres</aside>
- <div class="box-4">Box 4</div>
- <div class="box-5">Box 5</div>
- </div>
Alle Elemente in der Flexbox werden im nächsten Schritt mit einer festen Breite versehen:
- #beispiel-08 nav,
- #beispiel-08 aside,
- #beispiel-08 section,
- #beispiel-08 div {
- width: 150px;
- min-height: 100px;
- }
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.
- #beispiel-09 {
- -webkit-flex-wrap: wrap;
- flex-wrap: wrap;
- }
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.
- #beispiel-10 nav,
- #beispiel-10 aside,
- #beispiel-10 section,
- #beispiel-10 div {
- width: 150px;
- -webkit-flex-grow: 1;
- flex-grow: 1;
- -webkit-flex-basis: auto;
- flex-basis: auto;
- }
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.
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:
Zusätzlich wird ein Media-Query definiert:
- @media all and (max-width: 500px) {
- #beispiel-11 {
- -webkit-flex-direction: column;
- flex-direction: column;
- }
- }
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:
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.
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...
Christian
am 11.12.2012 - 13:17
Wieder ein sehr gelungener Artikel. Vielen Dank.
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.
Alex
am 11.12.2012 - 14:37
DANKE! Auch für Hobby-Webbastler sehr verständlich und anschaulich geschrieben.
Aaron
am 11.12.2012 - 14:39
Danke für den Überblick! Flexbox wird das Bauen von Layouts einiges praktischer machen.
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..
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
Mo
am 17.12.2012 - 09:49
Es gibt einen Polyfill für Flexbox: Flexie (https://github.com/doctyper/flexie)
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.
Die Kommentare sind geschlossen.