Wenn Sie an Webanwendungen arbeiten, die ältere Browser unterstützen, und von der Seitenlinie aus nach CSS Grid gelüstet haben, wie ich, habe ich gute Nachrichten: Ich habe einen cleveren, reinen CSS-Weg entdeckt, um die Grid-Auto-Platzierung in IE10+ zu nutzen!
Nun, es ist nicht *wirklich* CSS Grid, aber wenn man sich den Code nicht ansieht, würde man es nicht merken. Die HTML-Struktur sieht aus wie CSS Grid. Sie hat eine definierte Anzahl von Spalten mit einer undefinierten Anzahl von Zeilen und sie hat Abstände, die Ränder und Schatten auf den Zellen ohne Hacks unterstützen. Aber was tatsächlich hinter den Kulissen passiert, ist eine Kombination aus Flexbox und Margins.
In diesem Artikel werde ich den Ansatz Schritt für Schritt erläutern. Hier ist eine Demo dessen, was wir uns ansehen
Siehe den Stift
IE10-kompatibles CSS-Grid-ähnliches Spaltenlayout von Brian Holt (@bholtbholt)
auf CodePen.
Automatisch fließende Zeilen mit Flexbox-Wrap

Das grundlegende Grid-Setup ist sehr einfach. Wenn Sie mit Flexbox vertraut sind, haben Sie sich sicher schon gedacht, dass flex-wrap: wrap der Trick ist. Und Sie hätten Recht.
Lassen Sie uns zuerst das HTML-Markup erstellen, bevor wir CSS schreiben. Wir möchten, dass es der gleichen Struktur ähnelt, als würden wir Auto-Placement verwenden – ein .grid-Container und eine undefinierte Anzahl von .grid__cells.
<div class="grid">
<div class="grid__cell">...</div>
...
</div>
Wir legen drei Grid-Breakpoints fest. Ein einspaltiges, zweispaltiges und dreispaltiges Layout für Mobilgeräte, kleine Bildschirme und mittlere Bildschirme. Ich verwende die Breakpoints, die in Bootstrap verwendet werden, obwohl wir sie an den tatsächlichen Stellen definieren müssten, an denen das Layout bricht, wenn wir mit realen Inhalten arbeiten würden.
$screen-sm-min: 768px;
$screen-sm-max: 991px;
$screen-md-min: 992px;

Ein Mobile-first-Ansatz bedeutet, dass unser einspaltiges Layout bereits fertig ist, da jeder .grid__cell bereits ein Block ist. Wir setzen .grid so, dass es nach dem ersten Breakpoint zu einem Flexbox-Container wird und die Zellen umbricht.
@media (min-width: $screen-sm-min) {
.grid {
display: flex;
flex-wrap: wrap;
}
}
Unsere zwei- und dreispaltigen Layouts benötigen explizite Breiten und Flex-Eigenschaften; sonst werden sie auf einer einzigen Zeile gequetscht. Beim Testen von IE10 stieß ich auf unerwartetes Verhalten mit der flex-basis-Eigenschaft und stellte fest, dass das Festlegen einer expliziten Breite mit flex-basis: auto konsistenter war. Dies schien jedoch kein Problem mit IE11 zu sein.
.grid__cell {
min-width: 0;
flex: 1 1 auto;
}
// Two-column grid
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: 50%;
.grid__cell {
width: $width;
}
}
// Three-column grid
@media (min-width: $screen-md-min) {
$width: 33.33%;
.grid__cell {
width: $width;
}
}
Wir müssen .grid__cell nicht in einer Media Query verpacken, da seine Flex-Eigenschaften keine Wirkung haben, wenn das übergeordnete Element kein Flexbox-Container ist. Wir definieren auch eine Obergrenze für die zweispaltige Media Query, damit sie das dreispaltige Grid nicht beeinflusst.
Und das ist es! Wir haben jetzt ein responsives, flüssiges, umbrechendes Flexbox-Grid. Der einfache Teil ist erledigt ... na ja, solange wir immer nur Elemente haben, die Vielfache von zwei und drei sind. Mit flex: 1 1 auto nimmt das letzte Element immer den verbleibenden Platz in der letzten Zeile ein.


Ausrichten von Zellen in der letzten Zeile
Die schwer fassbare letzte Zeile ist der Grund, warum wir hier sind, oder? Standardmäßig dehnt sich jede Zelle in einer Flexbox-Layouts bis zum Ende der Zeile aus, aber Grid hinterlässt einen leeren Fleck. Wie machen wir das in Flexbox? Mit Pseudoelementen!
Der Trick besteht darin, dem .grid-Container ein Pseudoelement hinzuzufügen und es wie eine Zelle zu konfigurieren. Wir definieren die :after Pseudoelement-Zelle an jedem unserer Breakpoints mit der gleichen Breite wie eine echte Zelle.
@media (min-width: $screen-sm-min) {
.grid {
...
&:after {
content: '';
display: block;
flex: 1 1 auto;
}
}
}
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: 50%;
.grid:after {
width: $width;
}
}
@media (min-width: $screen-md-min) {
$width: 33.33%;
.grid:after {
width: $width;
}
}
Dies erzeugt eine gefälschte Zelle, die gegen unsere echten Zellen drückt und unser zweispaltiges Grid ausrichtet, wenn die Zellen ungerade sind. Wenn wir ihre Höhe undefiniert lassen, kann sie kollabieren, wenn die Zellen gerade sind.

Unser dreispaltiges Grid ist etwas komplexer, da wir mehrere Zustände handhaben müssen, wie z. B. wenn es eine leere Zelle gibt und wenn es zwei leere Zellen gibt.

Unser Zustand mit einer leeren Zelle ist bereits abgedeckt, da er sich nicht wirklich von einer leeren Zelle in zwei Spalten unterscheidet. Die :after-Zelle hat ihre Breite eingestellt und vervollständigt die Zeile. Die Geschichte ändert sich jedoch, wenn es zwei leere Zellen gibt, denn flex: 1 1 auto taucht wieder auf: Die letzte Zelle erstreckt sich nun über 50 % der Breite, wenn sie gegen das Pseudoelement gedrückt wird.

Mithilfe von CSS :nth-of-type-Selektoren können wir die erste Spalte in jeder Zeile ansprechen. Da unsere Zeilen Vielfache von drei sind, sprechen wir sie mit 3n an und zählen dann rückwärts um 2, um das erste Element in jeder Zeile zu erhalten.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2) {
background-color: red;
}
}
}

Wir sprechen grob alle Zellen in der ersten Spalte an, müssen die Auswahl aber auf die letzte Zeile beschränken. Tatsächlich müssen wir sie darauf beschränken, wenn es die letzte Zelle in der ersten Spalte der letzten Zeile ist. Glücklicherweise gibt es einen praktischen Pseudoselektor, um das letzte Element seiner Art anzusprechen. Wir verketten :last-of-type, um die logische Anweisung zu erstellen.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2):last-of-type {
background-color: red;
}
}
}
Nachdem wir nun die letzte Zelle in der ersten Spalte der letzten Zeile ausgewählt haben, verwenden wir einen Margin, um die :after-Zelle in die letzte Spalte zu verschieben und die mittlere Zelle zu füllen.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2):last-of-type {
margin-right: $width;
}
}
}
Hier ist unser mit Flexbox definierter Auto-Placement-Grid-Imitator im Ganzen. Betrachten Sie seine wunderschön ausgerichteten Zeilen. Ich wette, Sie können nicht einmal sagen, dass es nicht CSS Grid ist!

Abstände mit Margins hinzufügen
Die Spezifikation von CSS Grid hat eine Spalten- und Zeilenlücke, um Abstand zwischen jeder Zelle zu schaffen. Das Erstellen von Abständen in Flexbox ist viel schwieriger. Es sieht so aus, als würde es in Flexbox kommen, aber wir sind noch nicht so weit ... und IE wird es nie sein.
In Daniel Tonons Anleitung zu CSS Grid in IE verwendete er ein inneres Zellen-Div mit negativen Margins, Rändern, etwas Padding und overflow: hidden. Obwohl es vielleicht etwas hacky ist, funktioniert der Effekt, aber er verletzt unser Bestreben, eine CSS Grid-ähnliche HTML-Struktur beizubehalten. Der von mir bevorzugte Ansatz mag etwas roh erscheinen, aber ich fand ihn auch am einfachsten zu lesen und zu verstehen. Darüber hinaus verwendet er weiterhin :nth-of-type Pseudoselektoren, was den Gesamtansatz konsistent erscheinen lässt.
Wir möchten Lücken zwischen den Zellen, aber nicht außen herum. Wir möchten auch, dass unsere Zellen bündig mit dem Container abschließen.

Unser mobiles oder einspaltiges Grid benötigt nur einen unteren Margin an den Zellen. Wir fügen diesen hinzu und überschreiben die allerletzte Zelle mit margin-bottom: 0, damit die Zelle bündig mit dem Container abschließt. Normalerweise würde ich initial verwenden, aber es gibt keine Unterstützung in IE.
$col-gap: 16px;
.grid__cell {
...
margin-bottom: $col-gap;
&:last-of-type {
margin-bottom: 0;
}
}

Unsere zwei- und dreispaltigen Grids benötigen Margins auf der rechten Seite der Zellen, keine rechten Margins in der letzten Spalte und keine unteren Margins auf irgendeiner der Zellen der letzten Zeile. Aufgrund der Margins müssen wir auch unsere Breiten neu berechnen, da die Zellen umbrechen, wenn sie nicht passen.
In einem zweispaltigen Layout ist das Erreichen der rechten (oder zweiten) Spalte mit :nth-of-type(2n) oder :nth-of-type(even) recht einfach. Ich bevorzuge einen n-Multiplikator für die Konsistenz mit unserem dreispaltigen Grid und zur Berechnung der letzten Zeile.
Unsere letzte Zeile ist etwas kniffliger. Wenn wir ungerade Zellen haben, kümmert sich unser Mobile-first-CSS darum, die unteren Margins zu entfernen, da die Zelle die :last-of-type ist und unsere :after-Zelle keine Margins angewendet bekommt.

Wenn wir gerade Zellen haben, müssen wir die vorletzte Zelle ansprechen, aber nur, wenn sie sich in der ersten Spaltenposition befindet. Wenn wir sie nicht qualifizieren würden, würde die vorletzte Zelle vertikal wachsen, um der Höhe der vorletzten Zeile zu entsprechen. Wir können sie mit :nth-of-type(2n-1):nth-last-of-type(2) ansprechen.
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: calc(50% - #{$col-gap});
.grid__cell {
...
margin-right: $col-gap;
// Remove margin in last column
&:nth-of-type(2n) {
margin-right: 0;
}
// For when the last row is complete
// . .
// * .
&:nth-of-type(2n-1):nth-last-of-type(2) {
margin-bottom: 0;
}
}
}

Unsere dreispaltigen Abstände folgen dem gleichen Ansatz. Wir fügen allen einen margin-right hinzu, entfernen ihn aus der dritten Spalte und entfernen die unteren Margins aus der letzten Zeile. Wieder einmal wird unsere letzte Zelle durch unseren Mobile-first-Ansatz abgedeckt, aber jetzt müssen wir abdecken, wenn es zwei Zellen in der letzten Zeile gibt und wenn es drei Zellen gibt. Wir können unsere Selektoren mit nth-of-type und nth-last-of-type qualifizieren.
@media (min-width: $screen-md-min) {
$width: calc(33% - #{$col-gap});
.grid__cell {
...
margin-right: $col-gap;
// Remove margin in last column
&:nth-of-type(3n) {
margin-right: 0;
}
// For when there two items in the last row
// . . .
// * .
&:nth-of-type(3n-2):nth-last-of-type(2) {
margin-bottom: 0;
}
// For when the last row is complete
// . . .
// * * .
&:nth-of-type(3n-1):nth-last-of-type(2),
&:nth-of-type(3n-2):nth-last-of-type(3) {
margin-bottom: 0;
}
}
}

Wir müssen den Margin der letzten Zelle in der letzten Zeile anpassen, wenn sie aufgrund der Spalten allein ist. Wir verwenden 33 % plus einen Rand auf jeder Seite.
@media (min-width: $screen-md-min) {
$width: calc(33% - #{$col-gap});
.grid__cell {
...
// When there is only one item in the last rpw
// Fill the margin so it's like the last item is
// double the width
// . . .
// *->
&:nth-of-type(3n-2):last-of-type {
margin-right: calc(33% + #{$col-gap * 2});
}
}
}
Jetzt sind unsere Abstände installiert und das Grid ist komplett! Füllen Sie sie mit Rändern, Schatten oder was immer Ihr Herz begehrt.

Zusammenfassung
Hier ist noch einmal das Endergebnis
Siehe den Stift
IE10-kompatibles CSS-Grid-ähnliches Spaltenlayout von Brian Holt (@bholtbholt)
auf CodePen.
Ich glaube, diese Technik könnte mit kleineren Anpassungen auch IE9 unterstützen, z. B. durch die Verwendung von Inline-Blocks anstelle von Flexbox. Wir könnten auch zu einem vierspaltenen Grid erweitern, indem wir einen weiteren Breakpoint hinzufügen und den gleichen Ansatz wie beim dreispaltigen Grid verwenden. Fühlen Sie sich frei, diesen Ansatz zu verwenden, und ich hoffe, er hilft!
Ich unterstütze IE im Frontend offiziell nicht mehr. Juhu! Es ist wie die Freiheit, die ich fühlte, als ich aufhörte, IE 6 zu unterstützen. Der Fluch des Internets ist tot, so Microsoft.
https://techcommunity.microsoft.com/t5/Windows-IT-Pro-Blog/The-perils-of-using-Internet-Explorer-as-your-default-browser/ba-p0331732
Das ist für mich offiziell genug, einige relevante Zitate von Microsoft
„Internet Explorer ist eine Kompatibilitätslösung…“ (d. h. kein Browser)
Daher kann ich meinen Kunden, wenn sie sagen, dass ihre Website schlecht aussieht, jetzt sagen, dass sie ein System verwenden, das nicht für das moderne Web entwickelt wurde und nicht mehr unterstützt wird.
Daher bin ich der Meinung, dass Sie Webdesignern einen kleinen Nachteil tun, indem Sie die Arbeit mit toten Technologien fördern. Tabellen funktionieren mit IE 10 problemlos, keine Notwendigkeit, Flexbox einzubauen.
Hinweis: Der Kommentarbereich auf Ihrem neuen Design ist vom Inhalt getrennt, und ich habe das Gefühl, dass Sie Kommentare iterativ von Ihrer Website entfernen, indem Sie sie in die Fußzeile verlegen.
Könnten Sie die Pseudoelemente vermeiden und die Dinge stattdessen mit max-width einschränken? Es scheint eine sauberere Lösung zu sein und kann leichter auf mehr Spalten/Breakpoints erweitert werden.
Ich habe einen Pen zusammengestellt und ihn in IE10 getestet, und es scheint zu funktionieren.
Gedanken?
Die Einschränkung mit max-width ist ziemlich gut, aber ich hatte Schwierigkeiten, die letzte Spalte bündig mit dem .grid-Container zu bekommen, wenn ein Abstand vorhanden war.
Sie können den Margin zu allen Seiten der .grid__cell hinzufügen, wie Sie es in Ihrem CodePen getan haben. Dann müssen Sie den Margin vom .grid-Container abziehen, was unbeabsichtigte Auswirkungen auf umliegende Elemente haben kann.
Alles in allem denke ich, dass es ein weiterer guter Ansatz ist!