CSS/Tutorials/Grid/responsive Raster ohne Media Queries
Im Printdesign und auch bei „CSS-Frameworks“ wie bootstrap wird zuerst ein Gestaltungsraster erstellt, in dem die Rasterelemente dann fest platziert werden.
Im Webdesign mit seiner Unzahl von verschiedenen Viewportgrößen ist dies zwar auch möglich, oft aber gar nicht nötig.
In diesem Kapitel wird gezeigt, wie du mit wenigen CSS-Festlegungen Raster implizit erzeugst, deren Rasterelemente sich mit dem auto-placement-Algorithmus ohne den Einsatz von media queries responsiv anordnen.[1][2]
Inhaltsverzeichnis
Grundlagen
Blockelemente wie Überschriften oder Absätze nehmen im Standardverhalten der Browser stets die verfügbare Breite ein. Mit der Einführung von CSS wurde es möglich, Positionierungen und Größenangaben auch außerhalb des Elementflusses festzulegen.
Dies ermöglichte einerseits ein pixelgenaues Layout, wurde andererseits bei einer Änderung des Viewports zum Bumerang, da sich Inhalte außerhalb des sichtbaren Bereichs oder unter anderen Elementen befanden oder durch overflow: hidden;
abgeschnitten wurden. Media queries bieten hier eine Lösung, doch die immer wiederkehrende Frage nach den richtigen Breakpoints zeigt, dass aber auch dies nicht die einfachste Lösung ist.
Grid Layout beginnt wieder von vorne: Der verfügbare Raum wird aufgeteilt, weitere Inhalte werden innerhalb des Rasters in weiteren Reihen dargestellt und wandern so nach unten, wo man sie durch Scrollen erreichen kann.
Auch hier kann die Anzahl der Spalten mit media queries an die verfügbare Viewportbreite angepasst werden, wie schon in Kapitel 4 gezeigt wurde.
body{
display: grid;
grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 30em) {
body{
grid-template-columns: repeat(3, 1fr);
}
@media (min-width: 50em) {
body{
grid-template-columns: repeat(4, 1fr);
}
}
Fazit:
Mit media queries kann man ein Raster mit einer festen Spaltenanzahl, deren Breite sich flexibel anpasst, erzeugen.
Könnte man dies so umdrehen, dass man als Ausgangspunkt die Breite der Spalten nimmt, die sich entsprechend der Viewportbreite unterschiedlich oft nebeneinander anordnen?
Ja, das geht!
Responsivität ohne Media queries
Im Folgenden soll gezeigt werden, wie Raster mit flexibler Spaltenanzahl angelegt werden, die sich auch ohne Media Queries responsiv an den Viewport anpassen.
auto-fill
Bequemer als die Lösung mit media queries ist es allerdings, mittels des Schlüsselworts auto-fill
den Browser die Anzahl der Spalten automatisch festlegen zu lassen:
body{
display: grid;
grid-template-columns: repeat(auto-fill, 20em);
}
article {
grid-column: 1 / -1;
grid-row: span 2; }
}
grid-template-columns legt die Spalten eines Rasters fest.
Als Wert dient die repeat()-Funktion, die nun über den ersten Parameter auto-fill
so viele Spalten wie möglich erzeugt.
Der zweite Parameter gibt die Breite der Spalten (20em) vor.
Das article-Element soll, wenn der Platz ausreicht, breiter werden.
-
grid-column: 1 / -1;
legt fest, dass derarticle
an der ersten Gridlinie beginnt und an der letzten endet (negative Werte beginnen die Zählung rechts) -
grid-row: span 2;
das Element soll sich in der Höhe über 2 Reihen (Rasterfelder) erstrecken
Was fällt dir auf?
Bei großen Viewports:
Das body-Element erhält mit max-width: 75em;
eine Maximalbreite, die von den 3 je 20em breiten Rasterfeldern nicht völlig ausgefüllt wird.
Bei kleinen Viewports:
Das body-Element enthält 20em breite Raster, hat also dadurch eine feste Breite von 20em. Unterhalb dieser Viewportbreite ragt Inhalt aus dem sichtbaren Viewport; ein Scrollbalken wird angezeigt. Genau genommen bräuchte man hier eine media query, die das grid erst bei 40em Breite aktiviert:
@media (min-width: 40em) { display: grid; grid-template-columns: repeat(auto-fill, 20em); }
minmax()
Damit der autoplacement-Algorithmus seine volle Wirkung entfalten kann, muss die Breite der Spalten flexibel sein. Bisher wurde dies bei fester Spaltenanzahl mit der Einheit fr
erledigt. Nun sollen die Spalten eine feste Mindestgröße, aber auch keinen überschüssigen Raum in Form eines leeren Rands haben.
Voilà: Die minmax()-Funktion erlaubt es anstelle von festen oder relativen Längenangaben einen Mindest- und einen Maximalwert anzugeben:
@media (min-width: 40em) {
body {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
}
}
article {
grid-column: 1 / -1;
grid-row: span 2;
}
#news {
grid-column: span 2;
}
In diesem Beispiel wurde die repeat()-Funktion verwendet, die nun über den ersten Parameter auto-fill
so viele Spalten wie möglich erzeugt.
Der zweite Parameter besteht aus der minmax()-Funktion, die als Minimum einen Wert von 20em und, damit es z. B. bei 50em keine leeren Räume gibt, einen Maximalwert von 1 fr hat. Dann würden die 50em Breite in 2 Spalten a 25em Breite aufgeteilt.
Durch die Platzierung des article-Elements und der #news-Box über mehrere Spalten bleiben bei einem Dreispaltenlayout Rasterfelder frei.
grid-auto-flow
Wenn man Rasterelemente fest positioniert oder Gridbereiche festlegt, können im Raster wie im oberen Beispiel Lücken entstehen. Diese können mit im Markup nachfolgenden Elementen gefüllt werden.
Der autoplacement-Algorithmus kann durch die grid-auto-flow-Eigenschaft gesteuert werden.
Folgende Angaben sind möglich:
-
row
: (Standardwert) Die Spalten werden mit grid-template-columns explizit erzeugt; je nach Menge der Inhalte werden Zellen implizit erzeugt und in weiteren Reihen angefügt. -
columns
: Weitere Inhalte werden in implizit erzeugten Spalten angehängt. -
dense
: optionales Schlüsselwort, das kleinere Zellen in vorher entstandene Lücken platziert, sodass es zu einem gefüllten Raster kommt.
Ohne dieses Schlüsselwort kommt der sparse-Modus zum Zug, der Elemente, wenn kein Platz vorhanden ist, in die nächste Reihe schiebt. -
row dense
: -
column dense
:
body{
display: grid;
grid-template-columns: auto auto auto;
grid-auto-flow: dense;
}
article {
grid-column: 1 / -1;
grid-row: span 2;
}
#news {
grid-column: span 2;
}
Durch das Schlüsselwort dense
wird der Algorithmus so geändert, dass die vorher leeren Bereiche durch im Markup hinten stehende Elemente aufgefüllt werden.
dense
nur verwenden solltest, wenn es innerhalb des Grids keine fokussierbaren Elemente gibt, da eine Umordnung immer zu unlogischer Tab-Reihenfolge führt.Anwendungsbeispiele
Ein solch flexibles Raster eignet sich vor allem für gleichförmige Elemente, bei denen unter Umständen die Reihenfolge verändert werden kann, ohne dass es zu Irritationen wie einem weit oben stehenden Seitenfooter kommt.
Responsives Grid
Die 30 Artikel der Erklärung der Menschenrechte sollen sich flexibel über den verfügbaren Viewport verteilen. Dabei soll keine Spaltenanzahl vorgegeben werden:
main {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
color: black;
font: 1em/1.3 Cambria, serif;
}
main > section {
padding: 1rem;
background: hsl(220, 80%, 90%);
}
Für die 30 section-Blöcke werden mit grid-template-columns Spalten erzeugt. Dabei werden mit der repeat()-Funktion über das autofill
-Schlüsselwort so oft wie nötig Spalten mit einer durch die minmax(20em, 1fr)-Funktion ermittelten Breite von mindestens 20em Breite und maximal einem Bruchteil erzeugt.
Bildergalerie
Der auto-placement-Algorithmus eignet sich besonders für Listen und Galerien, bei denen die genaue Reihenfolge unwichtig ist. In dieser Bildergalerie werden die unterschiedlich großen Bilder auf den verfügbaren Platz verteilt. Durch grid-auto-flow: dense;
wird das Raster lückenlos gefüllt.
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(133px, 1fr));
gap: 10px;
grid-auto-flow: dense;
}
.gallery figure.landscape {
grid-column-end: span 2;
}
.gallery figure.panorama {
grid-column-end: span 3;
}
In diesem Beispiel findet das entscheidende CSS nur im Elternelement statt:
-
display: grid;
macht das div mit der idgallery
zum Grid Container -
grid-template-columns: repeat(auto-fill, minmax(133px, 1fr));
erzeugt Spalten, die mindestens 133px breit sind. Wenn die Gesamtbreite größer als ein Vielfaches der Mindestbreite ist, sodass normalerweise rechts ein Rand bliebe, verteilen die Spalten sich jedoch gleichmäßig über den verfügbaren Platz. -
grid-auto-flow: dense;
füllt das Raster lückenlos mit weiter hinten im Markup stehenden Elementen auf.
Neben dem Portrait-Modus, der eine Zelle umfasst, gibt es noch ein landscape-Format, das sich durch grid-column-end: span 2;
über zwei, sowie ein panorama-Format, das sich über 3 Zellen erstreckt.
.gallery figure {
border: thin solid #ccc;
position: relative;
margin: 0;
counter-increment: posMarkup;
}
.gallery figure img {
display: block;
object-fit: cover;
width: 100%;
height: 100%;
}
.gallery figure::after {
content: counter(posMarkup, decimal);
position: absolute;
bottom: 0;
color: red;
}
Die Bilder werden in ein figure-Element verpackt, das den browsereigenen Abstand durch margin: 0;
normalisiert.
Die Bilder werden durch object-fit: cover;
passend skaliert, ohne das Seitenverhältnis zu ändern.
Zur besseren Übersicht wie durch die Verwendung von dense
kleinere Zellen in vorher entstandene Lücken platziert werden, wird in einem absolut positioniertem Pseudoelement die Reihenfolge jedes Bildes gekennzeichnet. Dabei werden zur Bildnummerierung CSS-Counter verwendet:
- counter-increment erzeugt eine Variable, die dann im Pseudoelement
::after
übercontent: counter(posMarkup, decimal);
wieder ausgegeben wird.
Bilderwand aus Quadraten
Ist es möglich, eine Bilderwand mit Quadraten zu erzeugen, bei denen sich die Höhe an die flexible Breite anpasst?[3]
Das geht mit Grid layout und der aspect-ratio-Eigenschaft ganz einfach:
<div class="square-container">
<a id="kontakt" href="#">
Kontakt
</a>
<a id="weltwunder" href="#">
<img src="#" alt="Weltwunder" >
</a>
...
Das CSS wird nur über den .square-container
gesteuert:
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
grid-auto-rows: 1fr;
grid-auto-flow: dense;
max-width: 60em;
}
.square-container > * {
background: rgb(0 0 0 / 0.1);
border: thin solid transparent;
aspect-ratio: 1 / 1;
}
.square-container img {
object-fit: cover;
width:100%;
height: 100%;
vertical-align: top;
}
Damit die einzelnen Bilder, bzw. deren a-Elternelemente beim :hover
oder dem Durchtabben mit der →-Taste sichtbar werden, erhalten sie einen blauen Rand und eine verringerte Deckung:
.square-container > a {
border: 1px solid transparent;
position: relative;
}
.square-container > *:focus,
.square-container > *:hover {
border: 1px solid blue;
opacity: .75;
}
Innerhalb der Bilderwand soll es zwei quadratische Links auf den Blog und die Kontaktseite geben:
#blog,
#kontakt {
background: url(handwriting.jpg);
background-size:cover;
display:flex;
align-items:center;
justify-content:center;
font: 3rem bold;
text-decoration: none;
color: red;
}
#kontakt {
grid-column: -2 / -1;
}
Während der erste Link aufgrund seiner Reihenfolge im HTML oben links im Raster positioniert ist, wird der Link mit der #kontakt
mit grid-column oben rechts positioniert. Die negativen Werte zählen die Rasterlinien von rechts.
Masonry Tiles
Eine moderne Variante einer Bildergalerie ist das Masonry Layout, in dem sich Bilder innerhalb von flexiblen Spalten passend anordnen. Bis jetzt musste der Platzbedarf mit JavaScript verteilt werden - mit Grid Layout wird dies bald auch nur mit CSS möglich sein.[4]
Es gab verschiedene Entwürfe und bereits den Versuch einer Implementierung im FF79+. Diese wurden nun überarbeitet, funktionieren bisher (Stand: Oktober 2024) aber nur im Safari TP .
.grid-masonry {
display: grid;
gap: 1em;
grid-template-columns: repeat(auto-fill, minmax(9em, 1fr));
grid-template-rows: masonry;
}
- CSS Masonry & CSS Grid von Geoff Graham, 30.Sep.2024 (css-tricks)
- Help us choose the final syntax for Masonry in CSS 21.10.2024 von Jen Simmons
- How to Create a Masonry Layout Using HTML and CSS (freecodecamp.org)
Sobald die Spec festgelegt wurde und zwei Browser masonry unterstützen, werden wir diesen Abschnitt mit LiveBeispielen ausbauen.
--Matthias Scharwies (Diskussion) 05:39, 22. Okt. 2024 (CEST)
Siehe auch
Ein 3x3 (oder 4x4) Raster mit Großansicht und mehreren thumbnails.
- CSS/Tutorials/Grid/Einführung#Bilder-Galerie
- Bilderzoom mit Grid Layout
abgewandelte Version, in der die Bilder bei :hover in einer Großansicht gezeigt werden
Weblinks
- ↑ W3C: Automatic Placement: the grid-auto-flow property
- ↑ MDN: Auto-placement in CSS Grid Layout
- ↑ SELF-Forum: flexible Bilderwand vom 23.02.2020
2020 benötigte man dafür den padding-bottom height fix, mit dem einem Element ein unterer Rand von 100% bei einer Höhe von 0 gegeben wurde - der Prozentwert bezieht sich auf die Breite des Elements.
Als Vorlage für die Quadrate diente ein Pseudoelement, das als erstes Grid-Item die Größe festlegte:.square-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); grid-auto-rows: 1fr; grid-auto-flow: dense; } .square-container::before { content: ''; height: 0; padding-bottom: 100%; grid-row: 1 / 1; grid-column: 1 / 1; } .square-container > *:first-child { grid-row: 1 / 1; grid-column: 1 / 1; }
Heute verwendet man dafür aspect-ratio. - ↑ MDN: Masonry layout
- tutsplus: Understanding the CSS Grid “Auto-Placement Algorithm”
- sitepoint: A Step by Step Guide to the Auto-Placement Algorithm in CSS Grid von Nitish Kumar
- css-tricks: The Difference Between Explicit and Implicit Grids von Manuel Matuzovic (10.08.2017)
- Rachel Andrews: Flexible Sized Grids with auto-fill and minmax