Mit CSS-Grids zu Responsive Design

Flexbox im Einsatz
Kommentare

In einer Zeit mit unterschiedlichen Endgeräten und Auflösungen ist Responsive Design wichtiger denn je. Eine Webanwendung muss sich heute den Nutzerbedürfnissen anpassen und ihnen alle Informationen übersichtlich präsentieren. Flexbox und CSS Grids erfüllen diese Anforderungen.

Entwicklern stehen nun mehrere Gestaltungsmöglichkeiten zur Verfügung, die zwar auch mithilfe älterer Techniken realisierbar sind, mit CSS3 jedoch vereinfacht wurden. Dieser Artikel behandelt zwei dieser Techniken und erläutert den Umgang mit Flexbox und CSS Grids.

Mithilfe von Flexbox lässt sich auf einfache Weise ein Layout erzeugen. Im Mittelpunkt steht hierbei der so genannte Flex-Container. Dieser beinhaltet die Flex-Items, die innerhalb des Flex-Containers nach den Anforderungen des Layouts angeordnet werden. Flex-Items werden innerhalb des Containers an einer so genannten Flex Line ausgerichtet, die im Standard linksbündig und horizontal ausgerichtet ist. In Listing 1 ist das HTML-Grundgerüst dargestellt.

<body>
  <div id="container">
    <div>FlexItem1</div>
    <div>FlexItem2</div>
    <div>FlexItem3</div>
    <div>FlexItem4</div>
    <div>FlexItem5</div>
  </div>
</body>

Um die Funktionalität von Flexbox zu verwenden, wird dem Elternelement das Attribut display mit dem Wert flex zugewiesen. Das heißt, dass alle Items im Container nun als Flex-Items behandelt werden.

Wichtig: In der Literatur wird oft mit veralteter Syntax gearbeitet, was bedeutet, dass anstatt mit display:flex; mit display: flexbox; gearbeitet wird. Dieser Code ist aber nicht mehr zu verwenden. Listing 2 zeigt das CSS-Stylesheet für fünf linksbündig und horizontal ausgerichtete Boxen (Abb. 1).

Abb. 1: Ergebnis von Listing 2 – fünf Boxen linksbündig, horizontal

Abb. 1: Ergebnis von Listing 2 – fünf Boxen linksbündig, horizontal

#container {
  display: flex;
  border: 1px solid black;
  width: 100%;
}

#container > div {
  min-width: 80px;
  min-height: 80px;
  border: 1px solid black;
}

#container > div:nth-child(1) {
  background-color: green;
}

#container > div:nth-child(2) {
  background-color: yellow;
}

#container > div:nth-child(3) {
  background-color: red;
}

#container > div:nth-child(4) {
  background-color: purple;
}

#container > div:nth-child(5) {
  background-color: blue;
}

Die CSS-Eigenschaft flex-direction: row-reverse; sorgt dafür, dass die Flex-Items rechtsbündig angeordnet werden. Jedoch erfolgt die Anzeige der Items nun in umgekehrter Reihenfolge. Die Flex Line wurde somit gedreht (Abb. 2). Um die Ausgangsreihenfolge beizubehalten, muss im Ausgangscode die CSS-Eigenschaft flex-direction: flex-end benutzt werden. In Listing 3 ist die Verwendung von flex-direction: row-reverse; dargestellt.

Abb. 2: Änderung aus Listing 3 – rechtsbündig, umgekehrte Reihenfolge

Abb. 2: Änderung aus Listing 3 – rechtsbündig, umgekehrte Reihenfolge

#container {
  display: flex;
  border: 1px solid black;
  width: 100%;
  flex-direction: row-reverse;
}

Um die Reihenfolge der Flex-Items selbst zu bestimmen, steht die CSS-Eigenschaft order zur Verfügung. Listing 4 stellt das CSS-Stylesheet für das Ergebnis in Abbildung 3 bereit.

Abb. 3: Änderung aus Listing 4 – individuelle Anordnung der Boxen

Abb. 3: Änderung aus Listing 4 – individuelle Anordnung der Boxen

#container > div:nth-child(1) {
  background-color: green;
   order: 1;
}

#container > div: nth-child(2) {
  background-color: yellow;
  order: 3;
}

#container > div: nth-child (3) {
  background-color: red;
  order: 2;
}

#container > div: nth-child (4) {
  background-color: purple;
  order: 5;
}

#container > div: nth-child (5) {
  background-color: blue;
  order: 4;
}

In Listing 5 findet die CSS-Eigenschaft flex Verwendung, um den verschiedenen Flex-Items verschiedene Größen zuzuordnen. Die Flex-Items orientieren sich immer in Relation zu der Containerlänge, vgl. Abbildung 4 im Zusammenhang mit Listing 5.

Abb. 4: Anpassung der Containerlänge aus Listing 5

Abb. 4: Anpassung der Containerlänge aus Listing 5

#container > div {
  min-width: 80px;
  min-height: 80px;
  border: 1px solid black;
  margin: 5px;
}
#container > div: nth-child (1) {
  background-color: green;
  Flex: two;
}
#container > div: nth-child (2) {
  background-color: yellow;
  flex: 4;
}
#container > div: nth-child (3) {
  background-color: red;
  flex: 10;
}
#container > div: nth-child (4) {
  background-color: purple;
  flex: 4;
}
#container > div: nth-child (5) {
  background-color: blue;
  flex: 1;
}

Aber was passiert, wenn sich die Breite des Darstellungsbereichs ändert? Wünschenswert sind eine Neuanordnung und ein Umbrechen der Flex-Items. Mit flex-wrap:wrap werden die Flex-Items in Abhängigkeit von der Größe des Containers umgebrochen. Listing 6 erzeugt in Verbindung mit Listing 5 das Ergebnis in Abbildung 5.

Abb. 5: Anpassung an Darstellungsbereich durch Listing 5 und 6

Abb. 5: Anpassung an Darstellungsbereich durch Listing 5 und 6

#container {
  display: flex;
  border: 1px solid black;
  width: 100%;
  flex-wrap: wrap;
}

Unter Verwendung der vorgestellten Hilfsmittel sowie einiger CSS-Eigenschaften, die im nächsten Abschnitt vorgestellt werden, ist es möglich, ein komplizierteres Layout wie in Abbildung 6 zu gestalten. Das dreispaltige Layout besteht aus einem Header, einem Footer, einer Topnavigation und einem Inhaltsbereich. Im linken Bereich ist eine Anzeige der Topnews, im rechten Bereich sind Deep-Links vorgesehen.

Abb. 6: Mögliches, komplizierteres Layout

Abb. 6: Mögliches, komplizierteres Layout

Mithilfe von Media Queries wird das Layout an die Auflösung des Clients angepasst und somit responsiv. Listing 7 und 8 veranschaulichen die Umsetzungen eines Layouts, das sich zweistufig dem Darstellungsbereich anpasst, sobald dieser 800 Pixel Breite unterschreitet (vgl. Abbildung 7 von 600 Pixel bis 799 Pixel und Abbildung 8 kleiner 600 Pixel).

Abb. 7: Anpassung von Abbildung 6 bei 600–799 px

Abb. 7: Anpassung von Abbildung 6 bei 600–799 px

Abb. 8: Anpassung von Abbildung 6 bei weniger als 600 px

Abb. 8: Anpassung von Abbildung 6 bei weniger als 600 px

<body>
  <div class="layout">
    <header class="header">Flexbox - Layout</header>
      <nav class="topnavigation">
        <ul class="navigation">
          <li><a href="#">Start</a></li>
          <li><a href="#">Informationen</a></li>
          <li><a href="#">Kontakt</a></li>
          <li><a href="#">Impressum</a></li>
        </ul>
      </nav>
        <main class="content">
          <p>Lorem ipsum dolor sit amet…</p
          <p>Lorem ipsum dolor sit amet…</p>
        </main>
        <aside class="left">
          <ul class="news">
            <li><a href="#">News1</a></li>
            <li><a href="#">News2</a></li>
            <li><a href="#">News3</a></li>
          </ul>
        </aside>
        <aside class="right">
          <ul class="quicklinks">
            <li><a href="#">Quicklink1</a></li>
            <li><a href="#">Quicklink2</a></li>
            <li><a href="#">Quicklink3</a></li>
            <li><a href="#">Quicklink4</a></li>
          </ul>
        </aside>
    <footer class="footer">Footer</footer>
  </div>
</body>
.layout {
  display: flex;
  flex-flow: row wrap;
  font-weight: bold;
  text-align: center;
}

.layout > * {
  padding: 10px;
  flex: 1 100%;
}

.topnavigation {
  background: yellow;
}

.navigation {
  list-style: none;
  margin: 0;
  display: flex;
  justify-content: flex-end;
}

.topnavigation a {
  text-decoration: none;
  display: block;
  padding: 0.2em;
  color: black;
}

.topnavigation a:hover {
  text-decoration: none;
  display: block;
  color: violet;
}

aside ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  align-items: center;
  flex-flow: column wrap;
}

aside a {
  text-decoration: none;
  display: block;
  padding: 0.2em;
  color: black;
}

aside a:hover {
  text-decoration: none;
  display: block;
  color: violet;
}

.left li {
  border: 1px solid black;
  margin-bottom: 10px;
  width: 70px;
  height: 100px;
}

.left li:first-of-type {
  margin-top: 10px;
}

.header {
  background: blue;
}

.footer {
  background: green;
}

.content {
  text-align: left;
  background: gray;
}

.left {
  background: red;
}

.right {
  background: lightblue;
}

@media all and (min-width: 600px) {
  .left, .right {
     flex: 1 auto;
  }
}

@media all and (max-width: 600px) {
  .navigation {
      flex-flow: column wrap;
      padding: 0;
  }

  .topnavigation {
      padding: 0px;
  }

  .topnavigation a {
    text-align: center;
    padding: 10px;
    border-bottom: 1px solid black;
    border-top: 1px solid black;
  }
}

@media all and (max-width: 800px) {
  .navigation {
    justify-content: space-around;
  }

  .right {
    border-top: 1px solid black;
  }

  .left li {
    border: 0;
    margin-bottom: 2px;
    width: 100%;
    height: 20px;
  }

  .left li:first-of-type {
    margin-top: 5px;
  }
}

@media all and (min-width: 800px) {
  .content {
    flex: 3 0px;
    order: 2;
  }

  .left {
    order: 1;
    border: 1px solid black;
  }

  .right {
    order: 3;
  }

  .footer {
    order: 4;
  }
}

body {
  padding: 2em;
}

Flexbox: die wichtigsten Eigenschaften im Überblick

Die Gestaltungsmöglichkeiten mit Flexbox sind breit gefächert und zu weitgreifend, um ins Detail zu gehen. Im Folgenden werden die verschiedenen Möglichkeiten in CSS im Überblick dargestellt:

  • flex-direction row | row-reverse | column | column-reverse
  • justify-content: flex-start | flex-end | center | space-between | space-around – richtet die Flex-Items horizontal aus
  • align-items: flex-start | flex-end | center | baseline | stretch – richtet die Flex-Items vertikal aus
  • flex-wrap: nowrap | wrap | wrap-reverse – legt fest, ob ein Flex-Item umbricht, falls nicht mehr genug Platz vorhanden ist
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch – ähnlich wie align-Items, jedoch werden flex-lines angeordnet
  • flex-flow: <flex-direction> || <flex-wrap> – Zusammenfassung von flex-direction und flex-wrap
  • order: Anordnung innerhalb des Containers
  • align-self: auto | flex-start | flex-end | center | baseline | stretch – wird an Flex-Items verwendet und überschreibt die Eigenschaft align-items des Containers
  • flex: <flex-grow> <flex-shrink>? || <flex-basis>

CSS Grids

In der Vergangenheit verwendete man zum Layouten Tabellen und div-Elemente mit float. Mit Flexbox existiert nun eine Technik, die für eindimensionale Layouts verwendet werden kann. CSS Grids ermöglichen hingegen komplexe zweidimensionale Layouts. Da es sich bei CSS Grids noch um eine sehr junge Technik handelt, unterstützt sie nicht jeder Browser. Der Internet Explorer ab Version 10 und Edge unterstützen die Technologie nativ mit dem Präfix –ms.

Im Chrome-Browser unter chrome://flags muss die Einstellung „Experimentelle Webplattform-Funktionen“ aktiviert werden. Eine ähnliche Einstellung besitzen auch Opera und Firefox:

  • FF: about:config aufrufen und layout.css.grid.enabled auf True setzen
  • Opera: opera://flags aufrufen und Enable experimental Web Platform features aktivieren

Im Safari-Browser ist die Technologie standardmäßig in der Technical Preview aktiviert. Bei der Verwendung von CSS Grids werden der Inhalt und das Layout voneinander getrennt. Das Layout wird komplett in CSS beschrieben.

Ein CSS-Grid-Layout definiert ein Elternelement, in dem die Kindelemente positioniert werden. Listing 9 zeigt das HTML-Grundgerüst, mit dem in den folgenden Beispielen gearbeitet wird.

 
<body>
  <div class="grid">
    <div class="header">CSS-Grids</div>
    <div class="content">
      <p>Lorem ipsum dolor sit amet…</p>
      <p>Lorem ipsum dolor sit amet…</p>
    </div>
    <div class="left">Left Menu</div>
    <div class="right">Right Menu</div>
    <div class="footer">Footer</div>
  </div>
</body>

Mithilfe der CSS-Eigenschaft display und dem Wert grid wird in Listing 10 am Elternelement definiert, dass CSS Grids verwendet werden. Mit grid-template-columns und grid-template-rows wird das Raster beschrieben. Über grid-template-areas werden die Bereiche innerhalb des Rasters definiert.

 
grid {
  display: grid;
  grid-template-areas: "header header header" 
                       "leftnavigation content rightnavigation" 
                       "footer footer footer";
  grid-template-columns: 150px 1fr 150px;
  grid-template-rows: 100px 1fr 30px;
}

Um die Kindelemente innerhalb des Rasters zu positionieren, kann wie in Listing 11 über die Eigenschaft grid-area definiert werden, in welchem Bereich von grid-template-areas sich diese befinden.

 
header {
  grid-area: header;
  align-items: center;
  display: flex;
  justify-content: center;
  background-color: blue;
}

footer {
  grid-area: footer;
  align-items: center;
  display: flex;
  justify-content: center;
        background-color: green;
}
content {
  grid-area: content;
  background-color: gray;
}

left {
  grid-area: leftnavigation;
  background-color: red;
}

right {
  grid-area: rightnavigation;
  background-color: light blue;
}

Die vorangegangenen Listings produzieren das Ergebnis in Abbildung 9. Da die Benennung der Bereiche optional ist, lässt sich das gleiche Ergebnis mit dem Stylesheet in Listing 12 erreichen.

Abb. 9: Darstellung mit Grid-Layout (Listing 9–11)

Abb. 9: Darstellung mit Grid-Layout (Listing 9–11)

 
.header {
  align-items: center;
  display: flex;
  justify-content: center;
  background-color: blue;
  Grid-column-start: 1;
   rid-column-end: 4;
  grid-row-start: 1;
  Grid-row-end: 1;
}

.footer {
  align-items: center;
  display: flex;
  justify-content: center;
  background-color: green;
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 3;
  grid-row-end: 3;
}

..content {
  background-color: gray;
  grid-column-start: 2;
  grid-column-end: 2;
  grid-row-start: 2;
  grid-row-end: 2;
}

.left {
  background-color: red;
  grid-column-start: 1;
  grid-column-end: 1;
  grid-row-start: 2;
  grid-row-end: 3;
}

.right {
  background-color: light blue;
  grid-column-start: 3;
  grid-column-end: 3;
  grid-row-start: 2;
  grid-row-end: 3;

.grid {
  display: grid;
  grid-template-columns: 150px 1fr 150px;
  grid-template-rows: 100px 1fr 30px;
}

Hier werden mit den CSS-Eigenschaften grid-column-start, grid-column-end, grid-row-start und grid-row-end die Zeilen und Spalten direkt im Raster positioniert. Die Kurzschreibweisen hierfür sind grid-column: [start]/[end] und grid-row:[start]/[end].

Um nun die CSS Grids responsiv darzustellen, finden wiederum Media Queries Verwendung. Listing 13 als Erweiterung von Listing 12 produziert das in Abbildung 10 dargestellte Ergebnis.

Abb. 10: Ergebnis von Listing 9 und 12 mit Media Queries

Abb. 10: Ergebnis von Listing 9 und 12 mit Media Queries

 
@media screen and (max-width: 600px) {
  .grid {
    grid-template-areas: "header" "leftnavigation" "content"
    "rightnavigation" "footer";
    grid-template-columns: 100%;
    grid-template-rows: 100px 50px 1fr 70px 30px;
  }

  .left {
    align-items: center;
    display: flex;
    justify-content: center;
  }

  .right {
    align-items: center;
    display: flex;
    justify-content: center;
  }
}

Kombination beider Techniken

Im Gegensatz zu Flexbox, das sich bei linearen Entwürfen anbietet, eignen sich CSS Grids zur Darstellung von komplexen Strukturen und Verschachtelung. Das heißt, dass CSS Grids sich eher für das globale Layout einer Webanwendung anbieten und Flexbox auf einfache Weise den Inhalt präsentieren kann. Beide Techniken sind miteinander kombinierbar.

In Kombination mit dem HTML-Grundgerüst aus Listing 7 veranschaulicht Listing 13, wie beide Techniken miteinander harmonieren (Listing 14). Das Produkt ähnelt den Abbildungen 6 und 8.

.header {
  grid-area: header;
  align-items: center;
  display: flex;
  justify-content: center;
  background-color: blue;
}

.topnavigation {
  background: yellow;
  grid-area: topnavigation;
}

.navigation {
  list-style: none;
  margin: 0;
  display: flex;
  justify-content: flex-end;
  padding: 10px;
}

a {
  font-weight: bold;
}

.topnavigation a {
  text-decoration: none;
  display: block;
  padding: 0.2em;
  color: black;
}

.topnavigation a: hover {
  text-decoration: none;
  display: block;
  color: violet;
}

aside ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  align-items: center;
  flex-flow: column wrap;
}

aside a {
  text-decoration: none;
  display: block;
  padding: 0.2em;
  color: black;
}

aside a: hover {
  text-decoration: none;
  display: block;
  color: violet;
}

.left li {
  border: 1px solid black;
  margin-bottom: 10px;
  width: 70px;
  height: 100px;
}

.left li: first-of-type {
  margin-top: 10px;
}

.footer {
  grid-area: footer;
  align-items: center;
  display: flex;
  justify-content: center;
  background-color: green;
}

.content {
  grid-area: content;
  background-color: gray;
}

.left {
  grid-area: leftnavigation;
  background-color: red;
}

.right {
  grid-area: rightnavigation;
  background-color: light blue;
}

.layout {
  display: grid;
  grid-template-areas: "header header header" 
"topnavigation topnavigation topnavigation" "leftnavigation content rightnavigation" "footer footer footer";
  grid-template-columns: 150px 1fr 150px;
  grid-template-rows: 30px 45px 1fr 30px;
  }

@media screen and (max-width: 600px) {
  .layout {
    grid-template-areas: "header" "leftnavigation" "content" "top navigation" "rightnavigation" "footer";
    grid-template-columns: 100%;
    grid-template-rows: 100px 160px 1fr 160px 100px 50px;
  }

  .left {
    align-items: center;
    display: flex;
    justify-content: center;
  }

  .right {
    align-items: center;
    display: flex;
    justify-content: center;
  }

  .navigation {
    flex-flow: column wrap;
    padding: 0;
  }

  .topnavigation {
    padding: 0;
  }

  .topnavigation a {
    text-align: center;
    padding: 10px;
    border-bottom: 1px solid black;
    border-top: 1px solid black;
  }

  .left li {
    border: 0;
    width: 100%;
    height: 20px;
  }
}
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -