Quantcast
Channel: Webkrauts - für mehr Qualität im Web
Viewing all articles
Browse latest Browse all 243

Rasterfahndung: auf der Suche nach der besten Layouttechnik

$
0
0
Notizblock mit karierten Blättern / RasterGridlayout und Flexbox

Bei CSS3-Layouts denkt jeder gleich an Flexbox. Speziell zur Erstellung von Layouts ist aber eigentlich vom W3C das CSS Grid Layout Module vorgesehen. Ist das aber wirklich notwendig – bietet Flexbox nicht schon alles, was das Webdesigner-Herz begehrt?

Im Artikel seht ihr zuerst das Grundprinzip des Gridlayoutmoduls. Dann geht es um einen konkreten Vergleich von Flexbox und Gridlayout: Ihr seht, wie ihr mit beiden Layouttechniken ein Holy-Grail-Layout umsetzen könnt und wie sich die beiden Techniken in ihrer Herangehensweise unterscheiden.

… und die Browser?

Bei allen neuen Features stellt sich erst einmal die Frage nach der Browserunterstützung. In allen wichtigen Browsern gibt es eine grundlegende Unterstützung für das Gridlayoutmodul oder die Implementierung ist zumindest in Arbeit. Im Detail:

  • Im Internet Explorer ist ab Version 10 eine veraltete Version des Gridlayoutmoduls implementiert. Die Eigenschaften erkennt ihr an dem -ms-Präfix. Die Möglichkeiten des jetzigen Entwurfs gehen weit über das damals vorgesehene hinaus, einfache Gridlayouts lassen sich jedoch auch im Internet Explorer umsetzen.
  • Die neueste Version des Gridlayoutmoduls könnt ihr heute schon im Chrome ausprobieren, wenn die Unterstützung aktiviert ist. Dafür gebt ihr chrome://flags/ in die Adresszeile ein, sucht nach »Experimentelle Webplattformfunktionen aktivieren« und klickt auf »Aktivieren«. Ein paar ausgewählte Features funktionieren allerdings nur in Chrome Canary. Die hier vorgeführten Beispiele sind im Chrome bzw. Chrome Canary getestet.
  • Außerdem unterstützen die Webkit-Nightly-Builds das Gridlayoutmodul, die Eigenschaften müssen allerdings zusätzlich mit dem -webkit-Präfix versehen sein.
  • Im Firefox ist die Implementierung im Gange, es funktioniert allerdings – Stand Dezember 2015 – bisher nur ein Teil der Features. Dafür muss außerdem layout.css.grid.enabled gesetzt sein: Wenn ihr about:config in die Adresszeile eintippt, könnt ihr nach layout.css.grid.enabled suchen und durch Klick auf true einstellen.

Angesichts der Browserunterstützung ist es im Dezember 2015 nicht sinnvoll, Gridlayout bei echten Projekten einzusetzen; aber es ist der richtige Zeitpunkt, Gridlayouts zu testen und mit Chrome geht das sehr gut. Das Testen ist wichtig, denn so wie es aussieht, wird das Gridlayout die zentrale Technik sein, mit der Webworker in Zukunft Layouts realisieren werden. Und bevor die Spezifikation endgültig abgeschlossen ist, besteht die Chance, darauf Einfluss zu nehmen.

Raster, fertig, los!

Am Anfang steht die Definition des Rasters, als Basis dient dabei folgende HTML-Grundstruktur:

  1. <divclass="raster">
  2.   <divclass="a">A</div>
  3.   <divclass="b">B</div>
  4.   <divclass="c">C</div>
  5.   <divclass="d">D</div>
  6.   <divclass="e">E</div>
  7.   <divclass="f">F</div>
  8. </div>

Die Rasterdarstellung aktiviert ihr beim umfassenden Element durch die Angabe von display: grid. Dann definiert ihr die Ausmaße und die Anzahl der Rasterlinien. Ihr könnte damit horizontale und vertikale Linien festlegen – ganz wie bei einer Tabelle. Mit grid-template-columns legt ihr die vertikalen Rasterlinien fest, also z.B.:

  1. grid-template-columns: 100px150px180px;

Die Werte definieren die Positionen der Rasterlinien, der Einfachheit halber in Pixeln, zu einer flexibleren Lösung später.

Bei der Rasterdefinition wird die erste Linie nicht angegeben, sie befindet sich immer bei 0px. Mit grid-template-columns: 100px150px180px; bestimmt ihr also vier Linien: die erste befindet sich bei 0, die zweite nach 100px, die dritte 150px nach der zweiten und die letzte nach weiteren 180px. Ihr definiert also damit immer den Abstand der Rasterlinien voneinander. Nach demselben Prinzip funktioniert grid-template-rows, nur dass ihr damit die horizontalen Rasterlinien festlegt.

Der folgende Code legt ein Raster mit drei Spalten und zwei Zeilen an:

  1. .raster{
  2.   display: grid;
  3.   grid-template-columns: 100px150px180px;
  4.   grid-template-rows: 100px100px;
  5. }

Im Screenshot sind die Rasterlinien explizit eingezeichnet – rot die horizontalen, orange die vertikalen. Die Kindelemente verteilen sich dabei automatisch auf die Zellen.
Übrigens könntet ihr auch auf die Definition von Zeilen verzichten – dann werden automatisch so viele Zeilen eingefügt, wie vom Inhalt benötigt werden.

Definition eines Rasters mit drei Spalten und zwei Zeilen
Raster mit eingezeichneten Linien

In Position!

Im vorherigen Beispiel waren die Kindelemente automatisch angeordnet. Ihr könnt aber auch für jedes Element einzeln bestimmen, wo es beginnen und wo es enden soll. Auf diese Art könnt ihr angeben, dass sich ein Element über mehrere Rasterzellen erstrecken soll.

Die folgenden Codezeilen legen fest, dass .a an der ersten vertikalen Rasterlinie beginnt und bis zur zweiten geht. Außerdem soll es an der ersten horizontalen Linie beginnen und bis zur dritten reichen:

  1. .a{
  2.   grid-column-start: 1;
  3.   grid-column-end: 2;
  4.   grid-row-start: 1;
  5.   grid-row-end: 3;
  6. }
Das Element a erstreckt sich über zwei Spalten
Das Element a erstreckt sich über zwei Zeilen

Auf diese Art könntet ihr auch mehrere Elemente auf dieselben Zellen anordnen, die dann übereinander platziert werden – die zuletzt im Quellcode stehenden befinden sich oben.

… mit Zwischenraum, hindurchzuschauen

Beim Gridlayout wurde 2015 die Möglichkeit neu eingeführt, Zwischenräume zwischen den horizontalen (grid-row-gap) und den vertikalen Rasterlinien (grid-column-gap) zu definieren. In folgendem Beispiel gibt es 20px Abstand zwischen den vertikalen Rasterlinien und 30px Abstand zwischen den horizontalen Rasterlinien – das Beispiel funktioniert im Dezember 2015 allerdings nur in Chrome Canary und Webkit-Nightly-Builds.

  1. .raster{
  2.   display: grid;
  3.   grid-template-columns: 100px150px180px;
  4.   grid-template-rows: 100px100px;
  5.   grid-row-gap: 20px;
  6.   grid-column-gap: 30px;
  7. }
Raster mit Zwischenräumen
Raster mit Zwischenräumen

Diese Möglichkeit zur Definition von Zwischenräumen bedeutet eine große Vereinfachung. Beim ursprünglichen Entwurf wurden nämlich Zwischenräume wie normale Spalten/Zeilen behandelt und damit funktionierte bei Zwischenräumen die automatische Aufteilung nicht; da die Elemente sich ja sonst auch in den Zwischenräumen platziert hätten.

Abkürzungen

Für die Definition des Rasters und bei der Positionierung der einzelnen Elemente gibt es verschiedene Abkürzungen. So könnt ihr direkt statt grid-template-columns und grid-template-rows die Angaben direkt hinter grid schreiben. Der folgende Code

  1. grid: 100px150px180px / 100px100px;

bedeutet dasselbe wie

  1. grid-template-columns: 100px150px180px;
  2. grid-template-rows: 100px100px;

Auch bei der Positionierung der Elemente gibt es Varianten. Wenn ein Element sich nur bis zur nächsten Rasterlinie erstreckt, könnt ihr grid-column-end weglassen:

  1. grid-column-start: 1;
  2. grid-column-end: 2;

hat also dieselben Auswirkungen wie

  1. grid-column-start: 1;

Außerdem könnt ihr hinter grid-column bzw. grid-row direkt Anfangs- und Endlinie angeben:

  1. grid-column: 1 / 3;

Oder direkt alle Angaben hinter grid-area schreiben. Statt:

  1. grid-row: 2/5;
  2. grid-column: 3/6;

geht genauso auch

  1. grid-area: 2/3/5/6;

Die Reihenfolge der Angaben ist dabei etwas gewöhnungsbedürftig.

Zudem könnt ihr über span bestimmen, wie weit sich ein Element erstrecken soll – ähnlich wie rowspan und colspan bei Tabellen. Das folgende Element beginnt bei der ersten vertikalen Rasterlinie und erstreckt sich über zwei – es endet also bei der dritten vertikalen Rasterlinie.

  1. grid-row: 1 / span 2;

Voll flexibel

In den bisherigen Beispielen sind die Abstände zwischen Rasterlinien in Pixeln bestimmt. Für die Praxis ist es wichtig, dass ihr die Angaben flexibler gestalten könnt. Bei Flexbox ist dafür die Eigenschaft flex zuständig, bei Gridlayout ist es eine eigene Einheit, nämlich fr, was für »free space«, also »Anteil an freiem Platz« steht.

Ein Beispiel hierzu:

  1. grid-template-columns: 1fr 300px 2fr;

Wenn das umfassende Element 960px breit ist, dann berechnet sich die Breite der Spalten folgendermaßen: Zuerst zieht ihr die festen Breiten ab:

960px – 300px = 660px;

Dann könnt ihr den Wert von fr berechnen

660px : 3 (1fr + 2fr) = 220px

Damit hat im Beispiel die erste Spalte eine Breite von 220px und die letzte von 440px.

  1. grid-template-columns: 220px300px440px;

Interessant ist fr aber natürlich gerade dann, wenn die Gesamtbreite nicht festgelegt ist, sondern flexibel, weil sie sich etwa am Viewport orientiert.

Benannte Bereiche

Die CSS-Grid-Spezifikation ist umfangreich und bietet viele weitere Möglichkeiten wie benannte Linien oder die Anordnung der einzelnen Elemente. Die Ausrichtung funktioniert übrigens genauso wie bei Flexbox. Speziell für responsive Layouts sind die benannten Bereiche – die Eigenschaft grid-template-areas– äußerst praktisch:

  1. .raster{
  2.   display: grid;
  3.   grid-template-columns: 100px 1fr 100px;
  4.   grid-template-areas:
  5.     "kopf kopf kopf"
  6.     "navi haupt seite";
  7. }

Damit ist ein dreispaltiges Layout definiert, der Kopfbereich erstreckt sich über drei Spalten, darunter befinden sich die die drei Bereiche navi, haupt und seite. Wenn auf diese Art die Bereiche definiert sind, könnt ihr die Elemente beliebig darauf verteilen:

  1. .a{ grid-area: kopf; }
  2. .b{ grid-area: navi; }
  3. .c{ grid-area: haupt; }
  4. .d{ grid-area: seite; }
Rasterdefinition mit benannten Bereichen
Rasterdefinition mit benannten Bereichen

Das Praktische daran ist, dass die Logik des Rasters beim umfassenden Element definiert wird. Für andere Viewport-Größen definiert ihr einfach ein anderes Raster – wie das konkret geht, zeigt gleich das Holy-Grail-Layout.

Holy-Grail mit Flexbox

Sehen wir uns als Beispiel die Realisierung eines Holy-Grail-Layouts mit Flexbox und mit Gridlayout an (zu Flexbox siehe auch Ablösung für Float-Layouts und Flexbox light – das neue Layoutprinzip schon heute anwenden). Dabei gibt es folgende Anforderungen an das Layout:

  • Es ist ein dreispaltiges Layout mit gleich hohen Spalten.
  • Der Hauptinhaltsbereich steht im Quellcode ganz oben, wird aber in der dreispaltigen Darstellung in der Mitte angezeigt.
  • Die rechte und die linke Spalte haben feste Breiten, die mittlere Spalte ist flexibel.
  • Auf kleineren Screens soll das Layout einspaltig erscheinen.
Holy-Grail-Layout: dreispaltig
Holy-Grail-Layout: dreispaltig
Holy-Grail-Layout: einspaltig
Holy-Grail-Layout: einspaltig

Bei der Realisierung mit Flexbox dient folgende HTML-Grundstruktur als Basis:

  1. <header></header>
  2.  <divclass="main">
  3.     <article></article>
  4.     <nav></nav>
  5.     <aside></aside>
  6.   </div>
  7. <footer></footer>

.main wird zum Flexcontainer:

  1. .main{
  2.   display: flex;
  3. }

Damit werden die Kindelemente nav, article, aside automatisch nebeneinander angeordnet und gleich hoch. Die Eigenschaft order definiert die Reihenfolge – und flex bestimmt die Breite der Elemente. article erhält mit flex allen übrig bleibenden Platz, die anderen erhalten Breiten von 7em.

  1. article {
  2.   flex: 1;
  3.   order: 2;
  4. }
  5. nav {
  6.   flex: 007em;
  7.   order: 1;
  8. }
  9. aside {
  10.   flex: 007em;
  11.   order: 3;
  12.  }

Bei einer Maximalbreite von 40em sollen die Elemente untereinander und in der Quellcode-Reihenfolge dargestellt werden. Dafür sind zwei Dinge notwendig, zum einen ändert ihr die flex-direction, damit die Elemente untereinander angeordnet werden, und zum anderen stellt ihr über order: 0 die Anordnung wie im Quellcode wieder her:

  1. @media all and (max-width: 40em) {
  2.   .main{
  3.     flex-direction: column;
  4.   }
  5.   article, nav, aside {
  6.     order: 0;
  7.   }
  8.  }

Noch ein paar Anmerkungen zu dem Beispiel:

  • Es gibt natürlich unterschiedliche Ansätze, ein solches Layout zu realisieren. Das vorgestellte Beispiel orientiert sich an Using CSS flexible boxes.
  • >Das Beispiel zeigt nur die Standardsyntax; die für alle Browser benötigten Angaben erzeugt beispielsweise Autoprefixer sehr zuverlässig.
  • Außerdem ist manches ein bisschen komplexer, wenn ihr so viele Browser wie möglich an Bord holen wollt. In den Kommentaren bei solved-by-flexbox steht, was noch zu beachten ist.

Holy-Grail mit dem Gridlayout-Modul

Bei der Umsetzung des Layouts mithilfe des Gridlayout-Moduls gibt es eine Änderung bei der HTML-Struktur: Das .main-Element, das bei der Flexbox-Variante article, nav und aside umfasst, ist nicht notwendig – und würde auch stören:

  1. <header></header>
  2. <article></article>
  3. <nav></nav>
  4. <aside></aside>
  5. <footer></footer>

Dann geht es an die Definition des Rasters. body wird zum Rasterelement, die Aufteilung legt grid-template-areas fest:

  1. body {
  2.   display: grid;
  3.   grid-template-areas:
  4.   "header header header"
  5.   "nav article aside"
  6.   "footer footer footer";
  7.   grid-template-columns: 7em 1fr 7em;
  8.   grid-template-rows:
  9.     minmax(100px, min-content) 1fr minmax(100px, min-content);
  10. }

Erwähnenswert sind die Breitenangaben der Zeilen mithilfe der minmax()-Funktion: Hier gebt ihr den minimalen und den maximalen Wert an. Im Beispiel sollen header und footer mindestens 100px hoch sein und maximal so hoch wie es der Inhalt erfordert.

Die einzelnen Elemente verteilt ihr auf das Raster:

  1. article {
  2.   grid-area: article;
  3. } 
  4. nav {
  5.   grid-area: nav;
  6. }
  7. aside {
  8.   grid-area: aside;
  9. }
  10. header {
  11.   grid-area: header;
  12. }
  13. footer {
  14.   grid-area: footer;
  15. }

Damit steht die dreispaltige Darstellung. Für kleine Screens definiert ihr das Raster neu:

  1. @media all and (max-width: 40em) {  
  2.   body {
  3.     grid-template-areas:
  4.       "header "
  5.       "article"
  6.       "nav"
  7.       "aside"
  8.       "footer";
  9.      grid-template-columns: 1fr ;
  10.      grid-template-rows: 1fr 3fr 1fr 1fr 1fr;
  11.    }
  12.   }

Variationen

Das Praktische an der Gridlayout-Lösung ist, dass sich jetzt beliebige Zwischenvarianten definieren lassen – wie wäre es beispielsweise mit einer zweispaltigen Variante, bei der sich die Navigation über zwei Zeilen erstreckt?

HolyGrail-Layout: zweispaltig
HolyGrail-Layout: zweispaltig

Auch dafür ist nur eine Anpassung an der Rasterdefinition notwendig:

  1. @media all and (max-width: 55em) {
  2.   body {
  3.     grid-template-areas:
  4.       "header nav"
  5.       "article nav"
  6.       "aside aside"
  7.       "footer footer";
  8.     grid-template-columns: 3fr 1fr;  
  9.   }
  10. }

Ihr habt jetzt die vollkommene Freiheit bei der Anordnung und könnt auch header und footer miteinbeziehen.

Flexbox vs. Gridlayout – Fazit

Die Herangehensweise bei der Umsetzung eines Layouts mit Flexbox oder Gridlayout ist ganz unterschiedlich. Bei Flexbox kümmert sich der Webworker um die Anordnung einzelner Elemente – im Beispiel um die drei Spalten. Beim Gridlayout geht es hingegen um alle Komponenten der Webseite. Es ist problemlos möglich, Bereiche zu definieren, die sich über mehrere Zeilen des Rasters erstrecken und trotzdem einen Bezug zu den umgebenden Elementen haben.

Zusammengefasst hier die wichtigsten Fakten zu Flexbox und Gridlayout:

Browserunterstützung: Im Dezember 2015 ist Gridlayout noch nicht für den produktiven Einsatz geeignet. Flexbox hingegen könnt ihr heute verwenden, wenn ihr auf den IE9 verzichten könnt.

Einsatz: Flexbox ist für »eindimensionale« Anordnungen prädestiniert, also wenn es darum geht, Elemente entweder nebeneinander oder untereinander anzuordnen. Für komplexere Anordnungen müsstet ihr bei Flexbox hingegen mit Verschachtelungen arbeiten (Flexbox in Flexbox). Gridlayout ist hingegen genau für diese komplexeren, mehrdimensionalen Layouts vorgesehen, beispielsweise auch, wenn ein Element sich über mehrere Rasterzeilen erstrecken soll. Gerade für responsive Layouts ist es sehr praktisch, dass ihr für einzelne Viewportgrößen unterschiedliche Raster definieren könnt.

Kombination: Gridlayout und Flexbox lassen sich auch kombinieren: Eine gute Arbeitsaufteilung wäre, dass Gridlayout für das Grundlayout zuständig ist, aber beispielsweise für die Anordnung der Navigationspunkte Flexbox benutzt wird.

Grenzen von Gridlayout: Mit dem Gridlayout lassen sich flexible Rasteraufteilungen definieren, aber es hat auch Grenzen:

  • Mit Gridlayout sind etwa keine Masonry-Layouts möglich (wie etwa masonry.desandro.com). Das ist aber für die nächste Version der Spezifikation angedacht.
  • Gridlayout-Definitionen gelten immer für die Kindelemente. Schwierig kann es bei tiefer verschachtelten Elementen werden, wenn ihr beispielsweise beim Holy-Grail-Beispiel das main-Element beibehalten wolltet. Ihr könnt zwar Gridlayouts ineinander verschachteln, aber dann hat das verschachtelte Layout keinen Bezug zum umfassenden. Abhilfe bietet das subgrid-Feature, allerdings ist das derzeit »at risk« und wird vielleicht erst in der nächsten Version des Gridlayout-Moduls kommen.

Links

Florence Maurice

Viewing all articles
Browse latest Browse all 243