CSS/Tutorials/Layout mit Flexbox

Aus SELFHTML-Wiki
< CSS‎ | Tutorials
Wechseln zu: Navigation, Suche

In diesem Tutorial lernen Sie, wie Sie mit Flexbox eine Webseite erstellen, die sich problemlos an alle Viewports anpasst.

  • CSS 3.0
  • Chrome
  • Firefox
  • IE 11
  • Opera
  • Safari

Hinweis

Adventskalender 2017

Dieser Artikel ist der Beitrag zum 16. Dezember.

Zurück zum

Grundstruktur[Bearbeiten]

Als Grundstruktur verwenden wir unsere Webseite aus dem HTML5-Tutorial:

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
<body>
  <header>
    <!--- Kopfzeile --->
  </header>
  
  <article>
     <!--- Inhalt --->
  </article>

  <aside>
    <!---weiterführende Informationen --->
  </aside>

  <footer>
    <!--- Fußzeile --->
  </footer>
</body>

Responsivität[Bearbeiten]

Damit die Webseite sowohl in einem schmalen Browserfenster des Desktop-PCs als auch auf dem Smartphone oder Laptop wunschgemäß dargestellt wird, müssen Sie mithilfe eines meta-Elements dafür sorgen, dass sich die Seite an den Viewport anpasst.

Notieren Sie dazu folgende Zeile im head der Seite:

 <meta name="viewport" content="width=device-width, initial-scale=1.0">

Für weitere Erklärungen siehe HTML/Kopfdaten/meta#Viewport_einstellen.


maximale Breite festlegen[Bearbeiten]

Textzeilen, die sich über die gesamte Breite eines großen 4k-Monitors erstrecken, sind nur schwer lesbar.

Um die Breite des Inhaltsbereichs zu begrenzen und zu lange Textzeilen zu vermeiden, wurde dem body der Beispielseite eine maximale Breite zugewiesen.

Beispiel: Seite mit flexibler Breite
body {
    margin: 0 auto;
    max-width: 60em;
}

Mit margin: 0 auto wird die Seite zentriert.

Für <body> ist die CSS-Eigenschaft max-width: 60em; angegeben, um der Seite eine maximale Breite zu geben. Bei kleineren Viewports verringert sich die Breite, sodass die Seite nie breiter als der Bildschirm wird.


Empfehlung:
Verwenden sie für Ihr Layout keine festen Breitenangaben in Pixel. Wenn ein Benutzer die Schriftgröße im Browser ändert, wird im schlimmsten Fall Ihr Layout zerschossen.
Breitenangaben in relativen em passen Ihre Webseite flexibel an die Schriftgröße an!


ein flexibler Container[Bearbeiten]

Um ein flexibles Layout zu verwenden, müssen wir dem flexiblen Container-Element body ein display:flex; geben. Jetzt werden alle direkten Kind-Elemente zu Flex-Items. Diese Elemente können auch (wie hier im Beispiel) zu verschiedenen Typen gehören.

Empfehlung: Da nur die direkten Kind-Elemente ein flexibles Layout haben, empfiehlt es sich, eine zu große Verschachtelung von div-Elementen (Div-Suppe) von vorne herein zu vermeiden. Es ist mit Flexbox auch nicht mehr nötig.

Mit flex-direction können Sie festlegen, ob die Flex-Items in Reihen oder Spalten angelegt werden sollen. Hier wird der Standardwert row der horizontalen Anordnung übernommen. Mit flex-flow:wrap bestimmen Sie, dass Elemente in mehreren Reihen dargestellt werden, wenn sie (zusammen) die verfügbare Breite überschreiten.

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
body{
  display: flex;
  flex-flow: row wrap;
}

header, nav, footer {
  flex: 1 100%;
}

article {
  flex: 3 1 0%;
}

aside {
  flex: 1 1 0%;
}

Mit der Eigenschaft flex geben Sie den Elementen relative Größenangaben. Header, Navigation und Fußzeile erstrecken sich mit der Angabe 100% über die gesamte verfügbare Breite. Interessanter wird es beim Artikel und den beiden Asides: Mit dem flex-grow-Faktor bestimmen Sie, dass der Artikel dreimal so breit wie die Breite der aside-Boxen sein soll. Die genauen Werte berechnet der Browser dann automatisch!

Beachten Sie: CSS-Einstellungen wie position, float oder clear sind im flexiblen Layout nicht nötig. Angegebene Werte werden ignoriert.


vertikale Zentrierung[Bearbeiten]

Haben Sie im vorigen Beispiel gemerkt, dass sich die Höhe der article und aside-Boxen automatisch an der größten Höhe ausrichtet? Dies können Sie durch Angabe einer festen Höhe verhindern:

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
#news {
  height:120px;
  align-self: center;
}

Durch die Angabe der Eigenschaft align-self geben Sie dem News-Container ohne weitere Einstellungen eine vertikale Zentrierung.


horizontale Navigation[Bearbeiten]

Das flexible Layout beeinflusst nur die direkten Kind-Elemente. Für eine horizontale Navigation müssen nun der header selbst und nav ul zu flexiblen Containern werden.

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
header {
  display: flex;
  flex-flow: row wrap;  
}

header * {
  flex: 1 1 0%;
}

header img {
  flex: 0 0 400px;
  margin-right: 50px;
}  

header nav {
  flex: 1 1 100%;
}

nav ul {
  display: flex; 
  justify-content: space-around;
  flex-direction: row;
}

Das Logo bekommt eine feste Breite von flex: 0 0 400px;, damit es nicht verzerrt dargestellt wird. Anstelle des sonst üblichen display: inline-block; wird die horizontale Anordnung durch flex-flow festgelegt.


Das fertige Layout[Bearbeiten]

Auch wenn ältere Versionen des Internet Explorer noch nicht mit Flexbox umgehen können, werden wir nach dem Grundsatz Mobile First eine Grundstruktur für mobile Geräte und ältere Browser integrieren, die die Seiteninhalte trotzdem ansprechend darstellt. Alternativ können Sie auch ein Extra-Stylesheet für den IE 8 einbinden.


Mobile first[Bearbeiten]

Für kleinere Viewports setzen wir nun die Breiten für alle Blöcke und für die Navigationslinks auf 100%:

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
/* Mobile first - alle Dokument-Blöcke bekommen 100% Breite */  

header, nav, article, aside, footer {
  flex: 1 100%;
}
  
header {
  display: flex;
  flex-flow: row wrap;  
}
  
header * {
  flex: 1 1 0%;
}

header img {
  flex: 0 0 100px;
  height: 45px;
}  

header nav {
  flex: 1 1 100%;
}
  
nav ul {
  display: flex;  
  flex-direction: column;
}

nav li {
  margin: 1.3em 0;
  flex: 1 1 100%;
}

Der einzige Unterschied findet sich in der Anordnung: Während die Inhaltsblöcke mit flex-flow: row wrap; die ganze Breite ausfüllen und dann umbrechen, wird die Navigation mit flex-direction: column; in einer vertikalen Säule dargestellt - die Wirkung ist aber immer die gleiche.

Beachten Sie: Der IE11 hat Probleme, die einzelnen Navigationselemente untereinander darzustellen. Bei einer margin von 1.3em überdecken sie sich nicht mehr, in den anderen Browsern ist der Abstand so etwas größer.


Verschiedene Darstellungen je nach Viewport[Bearbeiten]

Viewports mit größerer Auflösung bekommen mit media-queries andere Einstellungen zugewiesen:

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
/* Smart Phones und Tablets mit mittlerer Auflösung */
@media all and (min-width: 35em) {
	
  header img {
    flex: 0 0 200px;
    height: 90px;
  }

  nav ul {
    flex-direction: row;
  }
  
  nav li {
    flex: 1 1 0%;
  }	

  /* durch auto werden die beiden asides in eine Zeile gesetzt */
  aside { 
    flex: 1 auto;
  }

  article { 
    order: 2; 
  }
  #news { 
    flex: 1 auto;
    order: 3; 
  }
  aside { 
    flex: 1 auto;
    order: 4; 
  }
  footer {
    order: 5;
  }
}

/* Smart Phones und Tablets mit mittlerer Auflösung */

@media all and (min-width: 35em) {
	header img {
		margin-right: 50px;
	}
	nav ul {
		-webkit-flex-direction: row;
		flex-direction: row;
	}
	nav li {
		margin: 0 10px;
		-webkit-flex: 1 1 0%;
		flex: 1 1 0%;
	}
	article {
		webkit-order: 2;
		order: 2;
	}
	#news {
		-webkit-flex: 1 auto;
		-webkit-order: 3;
		flex: 1 auto;
		order: 3;
	}
	aside {
		/* durch auto werden die beiden asides in eine Zeile gesetzt */
		
		-webkit-flex: 1 auto;
		-webikit-order: 4;
		flex: 1 auto;
		order: 4;
	}
	footer {
		webkit-order: 5;
		order: 5;
	}
}

/* Viewports mit großer Auflösung */
@media all and (min-width: 50em) {
/* article wird 2.5x so breit wie die beiden asides */
  article {                        
    order: 3;	
    flex: 5 1 0%;
  }

  aside {
    flex: 2 1 0%;
  }
  #news {
    flex: 2 1 0%;
    order: 2;
    align-self: center;
    height: 120px;  
  }
}

Ab 35em Breite wird die Navigation mittels der Eigenschaft flex-direction über die werte column und dann row nicht mehr in einer vertikalen Spalte, sondern in einer horizontalen Reihe dargestellt. Die einzelnen Listenpunkte werden automatisch auf die verfügbare Breite verteilt.

Abweichend vom Beispiel 1 wird der Inhaltsbereich nun nur 2,5 mal so breit wie die aside-Boxen. Dafür geben wir ihm einen flex-grow-Faktor flex: 5 1 0; gegenüber dem kleineren Faktor: flex: 2 1 0; für die Aside-Boxen.

aside-Boxen am Rand[Bearbeiten]

Beispiel: HTML5-Seite mit Grundstruktur ansehen …
/* Mobile first - alle Dokument-Blöcke bekommen 100% Breite */  

header, nav, article, aside, footer {
  flex: 1 100%;
}

/* Smart Phones und Tablets mit mittlerer Auflösung */
@media all and (min-width: 35em) {
	
  /* durch auto werden die beiden asides in eine Zeile gesetzt */
  #news { 
    flex: 1 auto;
    order: 3; 
  }

  aside { 
    flex: 1 auto;
    order: 4; 
  }
}

/* Viewports mit großer Auflösung */
@media all and (min-width: 50em) {
/* article wird 2.5x so breit wie die beiden asides */
  article {                        
    order: 3;	
    flex: 5 1 0%;
  }

  aside {
    flex: 2 1 0%;
  }
  #news {
    flex: 2 1 0%;
    order: 2;
    align-self: center;
    height: 120px;  
  }
}

Ändern sie die Anzeigebreite Ihres Browsers (z.B. mit <shift>+<strg>+<m> im Firefox) und beobachten Sie das Verhalten der beiden aside-Boxen. Bei kleinen Viewports nehmen die Boxen die gesamte Breite ein. Steigt die Breite über 35em, werden die beiden Boxen nebeneinander angeordnet. Dabei wird die Reihenfolge der Darstellung gegenüber dem Elementfluss mit order verändert.

Beachten Sie: Wenn Sie mit order eine abweichende Reihenfolge festlegen, müssen alle nachfolgenden Elemente (wie hier der footer) ebenfalls eine festgelegte Reihenfolge bekommen, da sie sonst an den Anfang rutschen.

Bei Auflösungen von 50em und höher wird die ursprüngliche Reihenfolge wieder hergestellt. Dafür bekommt die #News-Box auf der linken Seite jetzt eine feste Höhe und wird vertikal zentriert.

Wie geht's weiter?[Bearbeiten]

Mit diesem flexiblen Aufbau sind Sie für die Zukunft gerüstet.

Wenn Sie Interesse haben, können Sie im Bereich CSS/Tutorials


Weitere Beispiele, in denen Flexbox eingesetzt wird:


Weblinks[Bearbeiten]