Gestalten leerer Zellen mit generiertem Inhalt und CSS-Grid-Layout
Veröffentlicht: 2022-03-10Ein häufiges Grid-Layout-Problem ist, wenn ein Neuling in der Layout-Methode sich fragt, wie er eine Grid-Zelle formatieren soll, die keinen Inhalt enthält. In der aktuellen Level-1-Spezifikation ist dies nicht möglich, da es keine Möglichkeit gibt, auf eine leere Rasterzelle oder einen leeren Rasterbereich abzuzielen und Stile anzuwenden. Das bedeutet, dass Sie zum Anwenden des Stils ein Element einfügen müssen.
In diesem Artikel werde ich einen Blick darauf werfen, wie man CSS Generated Content verwendet, um leere Zellen zu formatieren, ohne redundante leere Elemente hinzuzufügen, und einige Anwendungsfälle zeigen, in denen diese Technik sinnvoll ist.
Ein genauerer Blick auf BFC
Wenn Sie jemals ein Layout mit CSS erstellt haben, wissen Sie wahrscheinlich, was BFC ist. Zu verstehen, warum es funktioniert und wie man es erstellt, ist hilfreich und kann Ihnen helfen, zu verstehen, wie Layout in CSS funktioniert. Lesen Sie einen verwandten Artikel →
Warum können wir leere Bereiche nicht schon stylen?
Der einleitende Absatz der Grid-Spezifikation sagt:
„Dieses CSS-Modul definiert ein zweidimensionales gitterbasiertes Layoutsystem, das für das Design von Benutzeroberflächen optimiert ist. Im Grid-Layout-Modell können die Kinder eines Grid-Containers in beliebigen Slots in einem vordefinierten Layout-Grid mit flexibler oder fester Größe positioniert werden.“
Der Schlüsselbegriff hier ist „Kinder eines Gittercontainers“. Die Spezifikation definiert die Erstellung eines Rasters auf dem übergeordneten Element, in dem untergeordnete Elemente positioniert werden können. Es definiert kein Styling dieses Rasters und geht nicht einmal so weit, etwas wie die Eigenschaft column-rule
zu implementieren, die wir im Multi-Column-Layout haben. Wir formatieren die untergeordneten Elemente und nicht das Raster selbst, was dazu führt, dass wir eine Art Element haben müssen, auf das wir diesen Stil anwenden können.
Verwendung redundanter Elemente als Styling-Haken
Eine Möglichkeit, etwas zum Gestalten einzufügen, besteht darin, ein redundantes Element in das Dokument einzufügen, z. B. eine Spanne oder ein Div. Entwickler mögen diese Idee eher nicht, obwohl sie seit Jahren zusätzliche redundante „Row Wrapper“ hinzufügen, um Grid-Layouts mit Floats zu erreichen. Vielleicht ist dieses offensichtlich leere Element unangenehmer als die etwas versteckte Redundanz des Wrapper-Elements!
Vollständig leere Elemente werden zu Gitterelementen und können mit Hintergründen und Rahmen versehen werden, genau wie ein Element, das Inhalt enthält, wie dieses Beispiel zeigt.
Sehen Sie, wie die Pen Empty-Elemente zu Grid Items von Rachel Andrew (@rachelandrew) auf CodePen werden.
Eric Meyer plädiert in seinem A List Apart-Artikel Faux Grid Tracks dafür, das b
Element als redundantes Element der Wahl zu verwenden, da es keine semantische Bedeutung verleiht, kurz ist und im Markup auch ziemlich offensichtlich als Haken ist.
Das Einfügen von ein paar zusätzlichen div
oder b
-Elementen ist wahrscheinlich nicht das größte Verbrechen gegen gutes Markup, das Sie jemals begangen haben, daher würde ich keinen Schlaf verlieren, wenn ich diesen Ansatz wählen würde, falls erforderlich. Bei der Webentwicklung geht es sehr oft darum, den am wenigsten suboptimalen Ansatz zu wählen, um die Arbeit zu erledigen, bis eine bessere Lösung gefunden wird. Ich ziehe es jedoch vor, mein Styling möglichst an einem Ort aufzubewahren, sicher im Stylesheet. Nicht zuletzt erleichtert es die Wiederverwendung von Stilen, ohne sich um das zusätzlich erforderliche Markup kümmern zu müssen. Aus diesem Grund tendiere ich dazu, auf generierten Inhalt zu schauen, etwas, das mir aus meiner Arbeit beim Formatieren von Büchern mit CSS sehr vertraut ist, wo Sie die meiste Zeit damit verbringen, mit dieser Funktion zu arbeiten.
Verwenden von generiertem Inhalt als Styling-Haken
CSS-generierter Inhalt verwendet die CSS-Pseudoklassen ::before
und ::after
zusammen mit der content
-Eigenschaft, um eine Art von Inhalt in das Dokument einzufügen. Die Idee, Inhalte einzufügen, könnte Sie zu der Annahme verleiten, dass dies zum Einfügen von Text dient, und obwohl dies möglich ist, sind wir für unsere Zwecke daran interessiert, ein leeres Element als direktes untergeordnetes Element unseres Grid-Containers einzufügen. Wenn ein Element eingefügt ist, können wir es stylen.
Im folgenden Beispiel habe ich ein enthaltendes Element, das zu meinem Grid-Container wird, in dem ein anderes Element verschachtelt ist. Dieses einzelne direkte Kind wird zu einem Grid Item. Ich habe ein dreispaltiges, dreizeiliges Raster auf dem Container definiert und dann das einzelne Element mithilfe von Rasterlinien so positioniert, dass es sich in der mittleren Rasterzelle befindet.
<div class="grid"> <div class="item"></div> </div>
.grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }
Wenn wir uns dieses Beispiel ansehen und den Firefox Grid Inspector verwenden, um die Gitterlinien zu überlagern, können wir sehen, wie die anderen leeren Zellen des Gitters existieren, aber um ihnen einen Hintergrund oder Rahmen hinzuzufügen, müssten wir ein zusätzliches Kind hinzufügen Elemente. Genau das ermöglicht Generated Content.

In meinem CSS füge ich einen leeren String hinzu, ::before
und ::after
my Grid Container. Diese werden sofort zu Gitterelementen und dehnen sich aus, um ihren Behälter zu füllen. Dann füge ich das Styling hinzu, das ich für die Boxen benötige, in diesem Fall füge ich eine Hintergrundfarbe hinzu, und positioniere sie wie jedes normale Rasterelement.
.grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; }

Im Dokument haben wir immer noch nur ein untergeordnetes Element, die redundanten Styling-Elemente sind im CSS enthalten, was durchaus vernünftig erscheint, da sie nur für Styling-Zwecke da sind.
Einschränkungen des Generated-Content-Ansatzes
Das offensichtliche Problem bei diesem Ansatz wird deutlich, wenn Sie sich entscheiden, auch die Rasterzellen oben rechts und unten links zu gestalten. Sie können nur einen Teil des generierten Inhalts auf den oberen und einen auf den unteren Teil des Containers anwenden, mehrere ::before
und ::after
-Pseudoelemente sind nicht zulässig. Die Methode wird nicht funktionieren, wenn Sie selbst ein CSS-Grid-Schachbrett erstellen möchten! Wenn Sie feststellen, dass Sie in absehbarer Zeit viel Leerzellen-Styling durchführen müssen, ist der oben erläuterte „Filler B“-Ansatz wahrscheinlich die beste Wahl.
Die generierte Inhaltsmethode könnte auch einen zukünftigen Entwickler verwirren, der an Ihrem Projekt arbeitet. Da wir auf den Container abzielen, bringt er den generierten Inhalt mit, wenn Sie diese Klasse an anderer Stelle wiederverwenden. Dies ist nützlich, wenn Sie dies wünschen. Im nächsten Beispiel haben wir dekorative Linien auf beiden Seiten einer Überschrift hinzugefügt, es wäre vernünftig, dass jede Instanz eines h1
diese Linien hätte. Es wäre jedoch sehr verwirrend, wenn Sie nicht wüssten, dass dies passieren würde! Hier hilft eine Kommentarzeile über den Containerregeln. Ich neige dazu, heutzutage in einer Musterbibliothek zu arbeiten, was diese Komponenten wirklich ordentlich an einem Ort unterstützt, wodurch deutlicher wird, was passiert, wenn eine Klasse auf ein Element angewendet wird.
Ausgefallene Überschriften
Einer meiner Lieblingstricks für generierte Inhalte ist das Stylen von Überschriften. In der Vergangenheit musste ich Überschriftenstile zurückdrängen, die zusätzliche Wrapper und absolute Positionierungsspuren erfordern würden, um sie zu erreichen. Wenn Inhalte aus einem CMS stammen, ist es oft unmöglich, diese redundanten Wrapper hinzuzufügen.
Mit Grid und generiertem Inhalt können wir auf beiden Seiten unserer Überschrift eine Zeile hinzufügen, ohne zusätzliches Markup hinzuzufügen. Die Zeile wächst und schrumpft je nach verfügbarem Platz und fällt elegant auf einen einfachen zentrierten Header zurück, wenn Grid in Browsern nicht verfügbar ist.


Unser Markup ist ein einfaches h1
.
<h1>My heading</h1>
In den Regeln für h1
erstelle ich ein dreispaltiges Raster. Der Wert von grid-template-columns
ergibt eine Spur von 1fr
dann eine von auto
und eine letzte Spur von 1fr
. Die beiden 1fr
Spuren teilen sich den verfügbaren Platz, der übrig bleibt, nachdem die Überschrift den Platz eingenommen hat, den sie benötigt, um innerhalb der Spur mit auto
Größe platziert zu werden.
Ich habe die Eigenschaft text-align
mit dem Wert center
hinzugefügt, damit meine Überschrift in Browsern ohne Raster eingegeben wird.
h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }
Wir fügen nun unseren generierten Inhalt hinzu, um eine Zeile vor und nach dem Überschriftentext hinzuzufügen. Ich verpacke diese Regeln in eine Funktionsabfrage, damit wir in Browsern ohne Grid-Layout keine seltsamen generierten Inhalte erhalten.
Die Linie selbst ist eine Umrandung des generierten Elements.
@supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }
Das ist alles, was Sie tun müssen! Sie können die gleiche Technik verwenden, um ein beliebiges Styling oder sogar ein Symbol auf beiden Seiten eines Elements über oder unter dem Element hinzuzufügen. Indem Sie Ihr Element in einer separaten Spur platzieren, wissen Sie, dass es keine Chance gibt, dass das Element Ihren Überschriftentext überlappt, was bei Versuchen mit absoluter Positionierung das Problem war. Sie haben auch den Vorteil, dass Elemente im Raster präzise aneinander ausgerichtet werden können.
Sehen Sie sich das Beispiel für die Überschrift Pen Generated Content von Rachel Andrew (@rachelandrew) auf CodePen an.
Dies ist ein nettes Beispiel für eine Verbesserung, die mit dem Grid-Layout möglich ist, die Sie nutzen können, auch wenn Sie noch nicht bereit sind, sich direkt in eine größere Neugestaltung mit Grid zu begeben. Es fällt sehr schön auf eine einfache Überschrift zurück, Leute mit unterstützenden Browsern bekommen den zusätzlichen Touch, und jeder bekommt den Inhalt. Ein ähnlicher Ansatz wurde von Eric Meyer gewählt, der generierte Inhalte verwendete, um einfach gestaltbare und positionierbare Zitate zu einem Blockquote-Element hinzuzufügen.
Bei diesen kleinen Funktionen denke ich oft nicht, dass ich Grid Layout verwenden werde. Als ich anfange herauszufinden, wie ich mein Design implementieren kann, wird mir klar, dass dies die zu wählende Layoutmethode ist. Aus diesem Grund ermutige ich die Leute, Grid nicht für das Seitenlayout und nicht für Komponenten zu halten, wenn Sie dies tun, verpassen Sie möglicherweise viele Gelegenheiten, bei denen es hilfreich sein kann.
Hinzufügen von Hintergründen und Rahmen zu Bereichen Ihres Designs
Wir können auch generierte Inhalte verwenden, um Gegenstände zu stapeln; Tatsache ist, dass mehr als ein Element eine bestimmte Rasterzelle einnehmen kann. Dies kann die mit generiertem Inhalt eingefügten Elemente umfassen.
Im nächsten Beispiel habe ich ein Design mit zwei Inhaltsabschnitten und einem Element in voller Breite. Hinter dem Inhalt befindet sich ein Hintergrund, der auch unter dem Element in voller Breite verläuft.

Das Markup hat einen Container mit den Abschnitten und dem Element voller Breite als direkte untergeordnete Elemente, und ich verwende die zeilenbasierte Platzierung, um meine Elemente im Raster zu platzieren.
<article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
.grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }
Dies gibt mir das Layout mit dem Bild in voller Breite und zwei platzierten Inhaltsabschnitten; Wenn ich den Abschnitten jedoch den Hintergrund hinzufüge, stoppt er über der row-gap
zwischen dem section
und dem Bild in voller Breite.
.section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

Wenn wir die grid-row-gap
entfernen und den Abstand durch Polsterung herstellen würden, würde dies immer noch nicht den Effekt des Hintergrunds ermöglichen, der unter dem Bedienfeld in voller Breite verläuft.
Hier können wir generierte Inhalte verwenden. Ich füge generierten Inhalt ::before
dem Grid-Container hinzu und gebe ihm eine Hintergrundfarbe. Wenn ich nichts anderes mache, wird der Inhalt in der ersten Zelle des Rasters positioniert.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

Ich kann den Inhalt dann mithilfe der zeilenbasierten Positionierung so positionieren, dass er sich über den Bereich erstreckt, der die Hintergrundfarbe zeigen soll.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
Das vollständige Beispiel sehen Sie in diesem CodePen.
Sehen Sie sich das Hintergrundbeispiel für stiftgenerierte Inhalte von Rachel Andrew (@rachelandrew) auf CodePen an.
Steuerung des Stacks mit z-index
Im obigen Beispiel wird der generierte Inhalt mit ::before
eingefügt. Das bedeutet, dass die anderen Elemente danach kommen, es befindet sich am Ende des Stapels und wird daher hinter dem Rest des Inhalts angezeigt, wo ich es haben möchte. Sie können den Stapel auch mit z-index
steuern. Versuchen Sie, den Selektor ::before
in ::after
zu ändern. Der generierte Inhaltshintergrund sitzt jetzt über allem, wie Sie an der Art und Weise sehen können, wie der Rahmen über das Bild verläuft. Denn es ist jetzt das Letzte im Gitterbehälter geworden, es wird zuletzt gestrichen und erscheint so „oben“.
Um dies zu ändern, müssen Sie diesem Element eine niedrigere z-index
Eigenschaft als allen anderen zuweisen. Wenn nichts anderes einen z-index
Wert hat, ist es am einfachsten, Ihrem generierten Inhalt einen z-index
von -1
zu geben. Dies führt dazu, dass es das erste Element im Stapel ist, als das Element mit dem niedrigsten z-index
.
.grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
Das Hinzufügen von Hintergründen auf diese Weise muss nicht darauf beschränkt sein, einen Hintergrund vollständig hinter Ihrem Inhalt abzulegen. In der Lage zu sein, Farbblöcke hinter einen Teil Ihres Designs zu platzieren, könnte einige interessante Effekte erzeugen.
Ist dies etwas, das die Spezifikation in Zukunft lösen könnte?
Das Hinzufügen von Hintergründen und Rahmen scheint ein fehlendes Feature der CSS-Grid-Spezifikation zu sein und eines, das die Arbeitsgruppe zusammen mit vielen Mitgliedern der Community diskutiert hat (der Diskussionsthread befindet sich auf GitHub).
Wenn Sie Anwendungsfälle haben, die mit generierten Inhalten nicht einfach zu lösen sind, dann fügen Sie Ihre Gedanken zu diesem Thread hinzu. Ihre Kommentare und Anwendungsfälle zeigen, dass Entwickler Interesse an der Funktion haben, und stellen außerdem sicher, dass jeder Vorschlag die Art von Dingen abdeckt, die Sie tun müssen.
Mehr Beispiele bitte!
Wenn dieser Artikel Sie ermutigt, mit generierten Inhalten zu experimentieren, oder wenn Sie bereits ein Beispiel haben, fügen Sie es bitte den Kommentaren hinzu. Jeder ist neu in der Verwendung von Grid in der Produktion, also gibt es viele: „ Daran habe ich nie gedacht! ” Momente, die wir haben werden, wenn wir Grid mit anderen Layoutmethoden kombinieren.