Flexbox Layout

Permalink

Aus gegebenen Anlass stand ein neuer Header für diesen Internetauftritt an. Anstelle des bisherigen Schriftzugs tritt ein Logo, ein Geschenk meiner Kollegen aus der Grafik. Das Menü soll rechts daneben wandern. Oberhalb des Menüs müssen aber noch drei Links untergebracht werden.

Diese Gelegenheit nutze ich um das CSS Flexible Box Layout Module in meinem CSS einzuführen. Ich finde das Konzept hinter diesem Layout-Modul recht vielversprechend. Es ermöglicht sehr flexible zeilen- oder spaltenweise Anordnung von Elementen. Die Kompatibilität ist auch recht gut wenn man auf veraltete Browser keine Rücksicht nimmt.

Schritt 1

Der erste Schritt besteht darin zwei nebeneinander angeordneter Bereiche zu erzeugen, einen für das Logo, einen für die Navigation.

<div id="toparea">
   <header role="banner"></header>
   <nav role="navigation"></nav>
</div>

Um das Flexbox-Modul zu aktivieren verwendet man den Wert flex für die CSS-Eigenschaft display. In diesem Fall sollen die beiden Elemente header und nav zeilenweise angeordnet werden. Dafür sorgt die Angabe flex-direction: row;. Mit justify-content: flex-start; sorgt man dafür das die Kindelemente von Links nach Rechts angeordnet werden.

Ein Vorteil von Flexboxen ist ihr Umgang mit dem verfügbaren Platz. Die Kindelemente, die sogenannten Flex-Items, erhalten soviel Platz wie sie benötigen. Sollte dann noch Platz in einer Zeile, respektive einer Spalte, übrig sein wird dieser nach einem festzulegenden Schlüssel verteilt. Diesen legt man über die Eigenschaft flex-grow für die einzelnen Items fest. Die damit angegebenen Werte definieren das Verhältnis der Elemente zueinander. Im vorliegenden Fall erhält das Logo keinen und die Navigation allen zusätzlichen Platz.

Die Kindelemente in einer Flexbox können natürlich unterschiedlich hoch (bei Spaltenanordnung: breit) sein. Die Eigenschaft align-items mit dem Wert stretch sorgt dafür das sie alle auf die gleiche Höhe ausgedehnt werden. So sind der Header und die Navigation immer gleich hoch.

#toparea {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: stretch;
  align-items: stretch;
}
#toparea > header {
  flex-grow: 0;
}
#toparea > nav {
  flex-grow: 1;
}

Beispiel bei jsFiddle

Schritt 2

Im zweiten Schritt wird die vertikale Anordnung der beiden Elemente im Bereich der Navigation realisiert. Dazu wird das Nav-Element in einen Flexbox-Container umgewandelt und die flex-direction als column definiert. Die weiteren Eigenschaften werden identisch zum ersten Schritt gesetzt.

<div id="toparea">
   <header role="banner"></header>
   <nav role="navigation">
      <div id="mainnav"></div>
      <div id="seqnav"></div>
   </nav>
</div>

Wie man am Markup ablesen kann ist die primäre Navigation oberhalb der Sekundären niedergeschrieben. Im Layout soll dies aber andersherum dargestellt werden. Hierzu kann auf die Eigenschaft order zurückgegriffen werden. Damit ist es möglich die Darstellungsreihenfolge innerhalb einer Flexbox unabhängig von derjenigen im Markup zu verändern.

#toparea nav {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: stretch;
  align-items: stretch;
}
#mainnav {
  flex-grow: 1;
  order: 2;
}
#seqnav {
  flex-grow: 0;
  order: 1;
}

Beispiel bei jsFiddle

Schritt 3

Im dritten Schritt wird der Zweck des Flexbox-Moduls ein wenig strapaziert. Um die Menüpunkte der Hauptnavigation zu strecken und unten auszurichten werden auch hier wieder Flexboxen verwendet obwohl es nicht direkt um die Umsetzung eines Rasters geht.

<div id="mainnav"></div>
   <ul>
      <li><a>Item 1</a></li>
      <li><a>Item 2</a></li>
      <li><a>Item 3</a></li>
   </ul>
</div>

Damit sich sowohl die Liste als auch die einzelnen Listenpunkte auf den gesamten verfügbaren Platz ausdehnen, werden diese wiederum als Flexboxen konfiguriert. Bei den Listenpunkten wird ein abweichender Wert für align-items verwendet: Der Wert flex-end sorgt dafür das die Schrift unten ausgerichtet wird.

#mainnav ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: stretch;
  align-items: stretch;
  flex-grow: 1;
}
#mainnav ul li {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: flex-start;
  align-items: flex-end;
}

Beispiel bei jsFiddle

Weitere Artikel zu CSS