Unsere Werkzeuge für vertikale Ausrichtung sind in letzter Zeit viel besser geworden. Meine frühen Tage als Webdesignerin bestanden darin, 960px breite Homepage-Designs zu layouten und Dinge horizontal über eine Seite mit einem 12-Spalten-Raster auszurichten. Media Queries kamen auf, was eine ernsthafte mentale Umstellung erforderte. Sie lösten natürlich einige große Probleme, führten aber auch neue ein, wie z. B. die Ausrichtung, wenn Elemente umbrechen oder anderweitig im Layout verschoben werden.
Schauen wir uns ein bestimmtes Szenario an: eine "Leiste" mit einigen Schaltflächen darin. Es gibt zwei Gruppen dieser Schaltflächen, die jeweils in einem <fieldset> mit einer <legend> enthalten sind.
Auf einem großen Bildschirm sind wir bereit

Und hier ist eine sehr einfache CSS-Methode, die dieses Layout erreicht und bei einem mobilen Breakpoint auch auf zwei "Zeilen" aufbricht
.accessibility-tools fieldset {
width: 48%;
float: left;
margin-right: 1%;
}
/* Mobile */
@media only screen and (max-width: 480px) {
.accessibility-tools fieldset {
width: 100%;
}
}
Auf einem kleinen Bildschirm erhalten wir dies

Das ist das Problem: fehlende vertikale Ausrichtung. Nehmen wir an, wir möchten diese Schaltflächen zu einer angenehmeren Anordnung ausrichten, bei der sich die Schaltflächenkanten schön aneinander ausrichten.
Um zu beginnen, könnten wir uns für feste, pixelbasierte CSS-Lösungen entscheiden, um Elemente bei verschiedenen Breakpoints schön auszurichten, indem wir Magische Zahlen wie diese verwenden
/* Mobile */
@media only screen and (max-width: 480px) {
legend {
width: 160px;
}
button {
width: 130px;
}
}

Das erledigt die Sache.
Aber... das ist nicht gerade eine flexible Lösung für das Problem. Abgesehen von den magischen Zahlen (feste Pixelwerte basierend auf spezifischem Inhalt) stützte es sich auch auf die Verwendung von Media Queries, von denen ich mich, wann immer möglich, entfernen möchte. Dies habe ich in einem Beitrag mit dem Titel "Stepping away from Sass" auf meinem Blog diskutiert.
Als ich mich moderneren CSS-Funktionen zuwandte, wurde die Notwendigkeit, bestimmte Bildschirmgrößen mit eindeutigem Code anzusprechen, beseitigt.
Was ich brauche, ist, dass jede Schaltfläche und jedes Label reagiert
- auf den verfügbaren Platz
- ihren Inhalt
und!
- andere Elemente um sie herum.
Verfügbarer Platz
Das Problem bei der Verwendung von Media Queries ist, dass sie den umgebenden Platz der neu ausgerichteten Elemente nicht berücksichtigen – ein Punkt, der in diesem Bild aus "The Flexbox holy albatross" von Heydon Pickering perfekt demonstriert wird.

Was ich wirklich will, ist, dass das zweite <fieldset> unter das erste umbricht, *nur wenn sie nicht mehr ordentlich auf eine Zeile passen.*
Können wir das mit Flexbox erreichen?
Ein Hauptverkaufsargument für Flexbox ist seine Fähigkeit, Elemente zu erstellen, die auf den umgebenden Platz reagieren. Komponenten können "flexen", um zusätzlichen Platz zu füllen und schrumpfen, um in kleinere Räume zu passen.
Für diese Situation ist die Eigenschaft flex-wrap auf wrap gesetzt. Das bedeutet, sobald beide <fieldset>-Elemente nicht mehr auf eine Zeile passen, werden sie auf eine zweite Zeile umgebrochen.
.wrapper--accessibility-tools {
display: flex;
flex-wrap: wrap;
}
Die Eigenschaft flex-wrap hat drei verfügbare Werte. Der Standardwert ist nowrap, wodurch Elemente auf einer Zeile bleiben. Der Wert wrap erlaubt es Elementen, auf mehrere Zeilen zu fließen. Dann gibt es noch wrap-reverse, das es Elementen erlaubt, umzubrechen, aber – warten Sie – in *umgekehrter Reihenfolge* (es ist seltsam zu sehen: wenn Elemente umbrechen, gehen sie in Links-nach-Rechts-Situationen über die vorherige Zeile).
Die Verwendung von Flexbox macht das Layout weniger starr, aber ein min-width-Wert ist immer noch erforderlich, um das Problem der vertikalen Ausrichtung zu beheben. Also: nah dran, aber noch nicht ganz.
Kann Grid uns helfen?
CSS Grid ist das allererste CSS-Modul, das speziell entwickelt wurde, um die anhaltenden Layoutprobleme zu lösen, mit denen Webdesigner und -entwickler konfrontiert sind. Es ist kein direkter Ersatz für Flexbox; vielmehr arbeiten die beiden Module normalerweise ziemlich gut zusammen.
Wie Flexbox kann Grid verwendet werden, um jedem <fieldset> so viel oder so wenig Platz wie nötig einzunehmen. Um gleich zur Sache zu kommen, können wir die Schlüsselwörter auto-fill und auto-fit (innerhalb einer repeat()-Funktion) nutzen, damit Grid-Elemente auf mehreren Zeilen fließen, ohne dass Media Queries erforderlich sind. Der Unterschied ist etwas subtil, aber gut erklärt in "Auto-Sizing Columns in CSS Grid: auto-fill vs auto-fit" von Sara Soueidan. Nehmen wir auto-fit.
.wrapper--accessibility-tools {
display: grid;
grid-template-columns: repeat(auto-fit, 450px);
grid-gap: 10px;
}
Ähnlich wie im Flexbox-Beispiel muss ich immer noch einen absoluten Wert für die Breite des Labels festlegen, um die <fieldset>-Elemente beim Stapeln auszurichten.
Ein weiterer Ansatz mit Grid
CSS Grid erlaubt es Elementen auch, basierend auf ihrem Inhalt mit flexiblen Grid-Spuren zu reagieren. Zusätzlich zu anderen Längeneinheiten wie Prozent, relativen Einheiten oder Pixel akzeptiert CSS Grid eine Fractional Unit (fr), wobei 1fr einen Teil des verfügbaren Platzes einnimmt, 2fr zwei Teile des verfügbaren Platzes einnimmt und so weiter. Richten wir hier zwei gleiche Spalten ein.
.wrapper--accessibility-tools {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
}
Es gibt auch eine minmax()-Funktion, die Grid-Spuren erstellt, die sich an den verfügbaren Platz anpassen, aber auch nicht schmaler als eine angegebene Größe werden.
.wrapper--accessibility-tools {
display: grid;
grid-template-columns: minmax(auto, max-content) minmax(auto, max-content);
grid-gap: 10px;
}
Beide Demos funktionieren und sind frei von absoluten Werten oder gerätespezifischem CSS. Die Ergebnisse sind jedoch weit von ideal entfernt, jede Grid-Struktur reagiert an unterschiedlichen Punkten. Vielleicht kein großes Problem, aber sicherlich nicht optimal.

Dies geschieht, weil beim Hinzufügen von display: grid zu einem Container nur die direkten Kinder dieses Containers zu Grid-Elementen werden. Das bedeutet, dass die von uns verwendeten intrinsischen Größeneinheiten nur auf Elemente im selben Grid bezogen sind.
Subgrid verwenden
Um mein Ziel wirklich zu erreichen, muss ich, dass die Schaltflächen und Labels auf Elemente in Geschwister-Grid-Containern reagieren. CSS Grid Level 2 beinhaltet die Subgrid-Funktion. Obwohl wir schon immer Grids verschachteln konnten, waren die Elemente in jedem Grid-Container unabhängig. Mit Subgrid können wir verschachtelte (Child-)Grids einrichten, die die Spuren von Elterngrid-Grids verwenden.
Dies macht viele zuvor schwierige Muster viel einfacher, insbesondere das "Card"-Muster, das das beliebteste Beispiel zu sein scheint, um die Vorteile von Subgrid zu zeigen. Ohne Subgrid wird jede Karte als unabhängiges Grid definiert, was bedeutet, dass die Spurengrößen in der ersten Karte nicht auf eine Höhenänderung in der zweiten reagieren können. Aus einem Beispiel, das Rachel Andrew verwendet hat von einem Beispiel, hier ist eine einfache Gruppe von Karten.

Subgrid erlaubt es den Karten, die auf dem Elterngrid definierten Zeilen zu verwenden, was bedeutet, dass sie auf Inhalte in umliegenden Karten reagieren können.

Jede Karte in diesem Beispiel nimmt immer noch drei Zeilenspuren ein, aber diese Zeilen sind nun auf dem Elterngrid definiert, wodurch jede Karte den gleichen vertikalen Platz einnehmen kann.
Für das Beispiel, mit dem wir gearbeitet haben, müssen wir keine Zeilen verwenden. Stattdessen müssen wir Spalten basierend auf Inhalten von Geschwister-Grids dimensionieren. Zuerst richten wir das Elterngrid so ein, dass es die beiden <fieldset>-Elemente enthält. Dies ähnelt dem Code, den wir zuvor im auto-fit-Demo betrachtet haben.
.wrapper--accessibility-tools {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-gap: 10px;
}
Dann positionieren wir jedes Subgrid auf dem Elterngrid.
.sub-grid {
display: grid;
grid-column: span 3;
grid-template-columns: subgrid;
align-items: center;
}

Alle Labels und Schaltflächen sind nun an den Spuren ihres Elterngrid ausgerichtet und bleiben konsistent. Sie haben jeweils eine gleiche Breite, basierend auf dem verfügbaren Platz. Wenn nicht genügend Platz für jedes verschachtelte Grid auf einer Zeile vorhanden ist, bricht das zweite in eine neue Zeile um.

Diesmal richten sich die beiden verschachtelten Grid-Elemente perfekt aus. Das Grid ist auch flexibel, wenn wir einen längeren Titel auf einer der Schaltflächen einfügen, reagieren die anderen Elemente entsprechend.


Browserkompatibilität
Die Unterstützung für Subgrid ist zum Zeitpunkt des Schreibens nicht großartig. Sie wird nur in Firefox 71+ unterstützt, obwohl es positive Signale von anderen Browsern gibt. CSS-Feature-Queries können verwendet werden, um alternative Stile für Chrome und Edge bereitzustellen.
Diese Browser-Supportdaten stammen von Caniuse, wo weitere Details zu finden sind. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 117 | 71 | Nein | 117 | 16.0 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 16.0 |
Beachten Sie, dass ich in diesen Demos einen zusätzlichen Wrapper um die Fieldsets verwende. Dies dient zur Behebung eines Fehlers bei Formelementen und Grid und Flexbox.
<fieldset class="accessibility-tools__colour-theme">
<div class="wrapper"></div>
</fieldset>
Das Layout-CSS wird auf den Wrapper angewendet, wobei das Fieldset auf display: contents gesetzt ist.
.accessibility-tools fieldset {
display: contents;
border: 0;
}
Weitere Lektüre zum Thema
- "Subgrid für bessere Kartenlayouts" von Miriam Suzanne
- "CSS Grid Level 2: Hier kommt Subgrid" von Rachel Andrew
- "The flexbox holy albatross" von Heydon Pickering
Ich bin wirklich begeistert, dass Subgrid jetzt von Firefox unterstützt wird!
Ich habe bemerkt, dass Ihr Subgrid-Beispiel unter 500 Pixel Breite nicht ganz funktioniert. Gibt es eine gute Möglichkeit, das ohne Media Queries zu beheben?
Oder sind Media Queries der beste Weg, dieses Problem zu beheben?
Toller Artikel. Ich werde dies als progressive Verbesserung in einige bevorstehende Projekte einbauen. Aber es wird großartig sein, sobald dies breitere Unterstützung findet.