Es ist schwer, das Gefühl zu übertreffen, eine perfekte Anwendung für eine neue Technologie zu finden. Man kann jede hilfreiche Einführung unter der Sonne lesen und bei auffälligen Demos staunen, aber wenn man sie zum ersten Mal im eigenen Projekt verwendet... dann wird es wirklich klar.
Ich habe eine neue Wertschätzung für CSS Grid gewonnen, als ich ein flexibles Layout für einen Konferenzzeitplan erstellt habe. Die Anforderungen des Projekts passten *perfekt* zu den Stärken von Grid: ein zweidimensionales (vertikales und horizontales) Layout mit komplexer Platzierung von Kindelementen. Bei der Erstellung eines Proof of Concept habe ich einige Techniken gefunden, die den Code sehr gut lesbar und geradezu unterhaltsam machten.
Die daraus resultierende Demo enthielt einige interessante Anwendungen von CSS Grid-Funktionen und zwang mich, mich mit einigen Details von Grid auseinanderzusetzen, die man im Alltag nicht antrifft.
Bevor wir beginnen, ist es vielleicht eine gute Idee, einen weiteren Tab mit dem CSS-Tricks-Leitfaden zu CSS Grid offen zu halten, um die Konzepte nachzuschlagen, die wir im Laufe des Beitrags behandeln.
Definition unserer Layout-Anforderungen
Ich habe versucht, das folgende Layout zu erstellen, dank WordCamp, den Hunderten von WordPress-fokussierten Konferenzen, die jedes Jahr auf der ganzen Welt stattfinden. Diese verschiedenen Veranstaltungen variieren in Größe und Format, verwenden aber alle das gleiche Tool für die Zeitplangestaltung.

Ich habe geholfen, ein paar WordCamps zu planen und eine WordCamp-Website zu gestalten, daher kannte ich die Nachteile des bestehenden HTML-Tabellenlayouts. Wenn Ihr Zeitplan nicht in ein einheitliches Raster passte, nun ja...¯\_(ツ)_/¯
Auf der Suche nach einem besseren Weg habe ich damit begonnen, die Layout-Anforderungen aufzulisten
- Sitzungen unterschiedlicher Dauer (begrenzt auf festgelegte Zeitschritte)
Stellen Sie sich aufeinanderfolgende einstündige Vorträge in drei Räumen neben einem zweistündigen Workshop in einem anderen vor. - Sitzungen, die sich über einen oder mehrere "Tracks" erstrecken
Tracks sind normalerweise mit einem bestimmten Raum im Veranstaltungsort verbunden. Im Fall meines lokalen WordCamps in Seattle kann der Veranstaltungsort buchstäblich eine Wand entfernen, um zwei Räume zu verbinden! - Zeitplan kann leeren Raum enthalten
Eine kurzfristige Absage oder eine besonders kurze Sitzung schafft Lücken im Zeitplan. - Design ist mit CSS einfach anzupassen
WordCamp-Websites erlauben Theming nur über CSS. - Layout kann automatisch aus CMS-Inhalten generiert werden
Da wir ein Layout aus strukturierten Sitzungsdaten von Tausenden von Websites erstellen, können wir uns nicht auf HTML oder CSS verlassen, das zu clever oder speziell ist.
Erste Schritte: Solides HTML
Bevor ich CSS schreibe, beginne ich immer mit einem absolut soliden HTML.
Das oberste <div> erhält die Klasse .schedule und dient als Grid-Elternteil. Jede eindeutige Startzeit erhält ihre eigene Überschrift, gefolgt von allen Sitzungen, die zu dieser Zeit beginnen. Das Markup für jede Sitzung ist nicht sehr wichtig, aber stellen Sie sicher, dass das Verständnis, wann und wo eine Sitzung stattfindet, nicht vom Layout abhängt. (Sie werden gleich sehen, warum.)
<h2>Conference Schedule</h2>
<div class="schedule">
<h3 class="time-slot">8:00am</h3>
<div class="session session-1 track-1">
<h4 class="session-title"><a href="#">Session Title</a></h4>
<span class="session-time">8:00am - 9:00am</span>
<span class="session-track">Track 1</span>
<span class="session-presenter">Presenter Name</span>
</div>
<!-- Sessions 2, 3, 4 -->
<h3 class="time-slot">9:00am</h3>
<div class="session session-5 track-1">
<h4 class="session-title"><a href="#">Session Title</a></h4>
<span class="session-time">9:00am - 10:00am</span>
<span class="session-track">Track 1</span>
<span class="session-presenter">Presenter Name</span>
</div>
<!-- Sessions 6, 7, 8 -->
<!-- etc... -->
</div> <!-- end .schedule -->
Mobiles Layout und Grid-Fallback abgeschlossen!
Mit etwas eigenem CSS, um die Dinge schön zu machen, ist unser mobiles Layout und das Fallback für Browser, die CSS Grid nicht unterstützen, bereits fertig!
So sieht es mit den von mir verwendeten Farben aus

Hinzufügen des Grid-Layouts
Nun zum eigentlichen CSS Grid-Teil!
Mein Aha-Erlebnis bei der Erstellung ergab sich aus der Lektüre von Robins Artikel hier auf CSS-Tricks, "Making a Bar Chart with CSS Grid." TL;DR: Eine Grid-Zeile repräsentiert 1% der Höhe des Diagramms, sodass ein Balken sich über die gleiche Anzahl von Zeilen erstreckt wie der Prozentsatz, den er darstellt.
.chart {
display: grid;
grid-template-rows: repeat(100, 1fr); /* 1 row = 1%! */
}
.fifty-percent-bar {
grid-row: 51 / 101; /* 101 - 51 = 50 => 50% */
}
Das half mir zu erkennen, dass Grid perfekt für jedes Layout ist, das an eine regelmäßige inkrementelle Einheit gebunden ist. Im Falle eines Zeitplans ist diese Einheit **Zeit**! Für diese Demo verwenden wir Schritte von 30 Minuten, aber machen Sie, was für Sie Sinn ergibt. (Passen Sie nur auf den Chrome-Bug auf, der Grid-Layouts auf 1000 Zeilen beschränkt.)
Die erste Version, die ich ausprobierte, verwendete eine ähnliche Syntax wie das Balkendiagramm in Robins Artikel und einige grundlegende mathematische Berechnungen, um die Sitzungen zu platzieren. Wir verwenden acht Zeilen, da es acht 30-Minuten-Intervalle zwischen 8 und 12 Uhr gibt. Denken Sie daran, dass die impliziten Grid-Liniennummern bei eins beginnen (nicht bei null), sodass die Grid-Zeilen von eins bis neun nummeriert sind.

.schedule {
display: grid;
grid-template-rows: repeat(8, 1fr);
}
.session-1 {
grid-row: 1 / 3; /* 8am - 9am, 3 - 1 = 2 30-minute increment */
}
.session-2 {
grid-row: 3 / 6; /* 9am - 10:30am, 6-3 = 3 30-minute increments */
}
Das Problem bei dieser Technik ist, dass das Platzieren von Elementen auf einem Raster mit vielen Zeilen sehr abstrakt und verwirrend ist. (Dieses Problem fügte auch Robins Balkendiagramm-Demo eine Menge Komplexität hinzu.)
Hier kommen benannte Grid-Linien ins Spiel! Anstatt sich auf Grid-Liniennummern zu verlassen, können wir jeder Linie einen vorhersehbaren Namen geben, der auf der entsprechenden Tageszeit basiert.

.schedule {
display: grid;
grid-template-rows:
[time-0800] 1fr
[time-0830] 1fr
[time-0900] 1fr
[time-0930] 1fr;
/* etc...
Note: Use 24-hour time for line names */
}
.session-1 {
grid-row: time-0800 / time-0900;
}
.session-2 {
grid-row: time-0900 / time-1030;
}
Das ist herrlich einfach zu verstehen. Es gibt keine komplizierte Mathematik, um herauszufinden, wie viele Zeilen sich vor und nach dem Beginn oder Ende einer Sitzung befinden. Noch besser ist, dass wir Grid-Liniennamen und Sitzungs-Layout-Stile mit in WordPress gespeicherten Informationen generieren können. Geben Sie dem Grid eine Start- und Endzeit, und Sie sind startklar!
Da der Zeitplan mehrere Tracks hat, benötigen wir eine Spalte für jeden. Die Tracks funktionieren ähnlich wie die Zeiten, wobei benannte Track-Linien für jede Grid-Spaltenlinie verwendet werden. Es gibt auch eine zusätzliche erste Spalte für die Überschriften der Startzeiten.
.schedule { /* continued */
grid-template-columns:
[times] 4em
[track-1-start] 1fr
[track-1-end track-2-start] 1fr
[track-2-end track-3-start] 1fr
[track-3-end track-4-start] 1fr
[track-4-end];
}
Hier gehen wir mit benannten Grid-Linien noch einen Schritt weiter. Jede Linie erhält *zwei* Namen: einen für den Track, auf dem sie beginnt, und einen für den Track, auf dem sie endet. Dies ist nicht unbedingt erforderlich, macht den Code aber viel klarer, insbesondere wenn sich eine Sitzung über mehr als eine Spalte erstreckt.
Mit den zeit- und trackbasierten Grid-Linien können wir nun jede gewünschte Sitzung platzieren, nur indem wir ihre Zeit und ihren Track kennen!
.session-8 {
grid-row: time-1030 / time-1100;
grid-column: track-2-start / track-3-end; /* spanning two tracks! */
}
Wenn wir all das zusammenfügen, erhalten wir einen langen, aber *extrem* lesbaren Code, mit dem es eine wahre Freude ist, zu arbeiten.
@media screen and (min-width: 700px) {
.schedule {
display: grid;
grid-gap: 1em;
grid-template-rows:
[tracks] auto /* Foreshadowing! */
[time-0800] 1fr
[time-0830] 1fr
[time-0900] 1fr
[time-0930] 1fr
[time-1000] 1fr
[time-1030] 1fr
[time-1100] 1fr
[time-1130] 1fr
[time-1200] 1fr;
grid-template-columns:
[times] 4em
[track-1-start] 1fr
[track-1-end track-2-start] 1fr
[track-2-end track-3-start] 1fr
[track-3-end track-4-start] 1fr
[track-4-end];
}
.time-slot {
grid-column: times;
}
}
<div class="session session-1 track-1" style="grid-column: track-1; grid-row: time-0800 / time-0900;">
<!-- details -->
</div>
<div class="session session-2 track-2" style="grid-column: track-2; grid-row: time-0800 / time-0900">
<!-- details -->
</div>
<!-- etc... -->
Der endgültige Code verwendet Inline-Stile für die Sitzungsplatzierung, was sich für mich richtig anfühlt. Wenn Ihnen das nicht gefällt und Sie mit moderneren Browsern arbeiten, könnten Sie die Namen der Linien über CSS-Variablen an CSS übergeben.
Kurzer Hinweis: Verwendung von fr-Einheiten vs. dem auto-Wert für Zeilenhöhen
Ein Detail, das erwähnenswert ist, ist die Verwendung der fr-Einheit zur Definition von Zeilenhöhen.
Bei Verwendung von 1fr zur Bestimmung der Zeilenhöhen haben alle Zeilen die gleiche Höhe. Diese Höhe wird durch den Inhalt der höchsten Zeile im Zeitplan bestimmt. (Ich musste die W3C-Spezifikation für fr lesen, um das herauszufinden!) Das erzeugt einen schönen Zeitplan, bei dem die Höhe proportional zur Zeit ist, kann aber auch zu einem *sehr* hohen Layout führen.

1fr erzeugt gleich hohe Zeilen, die von der höchsten Zeile im Grid bestimmt werden. (Demo ansehen: Grid-Zeilenhöhen 1fr vs auto)Wenn Ihr Zeitplan-Grid beispielsweise 15-Minuten-Intervalle von 7 bis 18 Uhr hat, sind das insgesamt 48 Grid-Zeilen. In diesem Fall möchten Sie wahrscheinlich auto für Ihre Zeilenhöhe verwenden, da der Zeitplan mit jeder Grid-Zeile, deren Höhe durch ihren Inhalt bestimmt wird, viel kompakter ist.

auto macht jede Zeile so hoch wie ihr Inhalt. (Demo ansehen: Grid-Zeilenhöhen 1fr vs auto)Ein Wort zur Barrierefreiheit
Es gibt ernsthafte Bedenken hinsichtlich der Barrierefreiheit bestimmter CSS Grid-Techniken. Insbesondere die Möglichkeit, die Reihenfolge von Informationen visuell zu ändern, die nicht mit der Quellreihenfolge übereinstimmt, verursacht Probleme für Menschen, die eine Tastaturnavigation verwenden.
Dieses Layout nutzt diese Fähigkeit, Elemente beliebig auf einem Grid zu platzieren, daher ist Vorsicht geboten. Da jedoch die Überschrift und die Quellreihenfolge mit der Visualisierung der Startzeiten übereinstimmen, scheint dies für mich eine sichere Anwendung zu sein.
Wenn Sie von ähnlichen Dingen inspiriert werden, **denken Sie sorgfältig über die Barrierefreiheit nach**. Es ist sinnvoll, Informationen in diesem Fall nach Zeit zu ordnen, aber ich kann mir ein legitimes Szenario vorstellen, in dem die `TAB`-Reihenfolge eher nach Spalten als über Zeilen verläuft. (Die Modifizierung dieser Demo, um dies zu erreichen, sollte nicht allzu schwierig sein!)
Was auch immer Sie tun, denken Sie immer an die Barrierefreiheit.
Hinzufügen von Sticky-Track-Namen
Schließlich ist es an der Zeit, die Track-Namen hinzuzufügen, die wie Tabellenüberschriften am oberen Rand jeder Spalte aussehen. Da der Track einer Sitzung bereits sichtbar ist, habe ich mich entschieden, die "Überschriften" mit aria-hidden="true" vor assistiven Technologien zu verbergen.
Die Track-Namen befinden sich in der ersten Grid-Zeile, die praktisch "tracks" genannt wird. Solange Sie keine komischen Überlaufprobleme haben, halten position: sticky diese beim Scrollen im Blick.
<span class="track-slot" aria-hidden="true" style="grid-column: track-1;">Track 1</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-2;">Track 2</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-3;">Track 3</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-4;">Track 4</span>
.track-slot {
display: none; /* only visible with Grid layout */
}
@supports( display:grid ) {
@media screen and (min-width:700px) {
.track-slot {
grid-row: tracks;
display: block;
position: sticky;
top: 0;
z-index: 1000;
background-color: rgba(255,255,255,.9);
}
}
}
Es ist ein schnelles, kleines Finish für die endgültige Demo. ✨
Das Ergebnis
So sehen die Dinge aus, wenn alles, was wir behandelt haben, zusammengefügt wird!
Siehe den Pen
Conference Schedule with CSS Grid von Mark Root-Wiley (@mrwweb)
auf CodePen.
Wir fangen gerade erst an
Dieser Zeitplan ist definitiv die befriedigendste Verwendung von CSS Grid, die ich je gemacht habe. Ich liebe, wie "datengetrieben" und semantisch die Benennung der Linien ist, und die Anforderungen an Barrierefreiheit und CMS passen perfekt hinein, ohne jegliche Unannehmlichkeiten.
Die einzige Frage, die für mich übrig bleibt, ist: Welche anderen Arten von "datengetriebenen" Grids gibt es noch zu erstellen? Ich habe einige tolle Kalender-Layouts gesehen und hier ist ein Monopoly-Brett-Layout. Was ist mit einem Fußballfeld, einer Zeitleiste, Restauranttischen oder Theatersitzen? **Was noch?**
Das ist eine erstaunliche Anwendung des Grids. Herzlichen Glückwunsch, Mark, Sie haben uns inspiriert.
Brillante Nutzung von Grid, eine super saubere Art, diese Zeitplan-Layouts zu erstellen. Ich hätte standardmäßig nach JavaScript gegriffen, aber jetzt denke ich, dass ich tiefer in das Experimentieren mit Grid eintauchen muss.
Großartige Zusammenfassung. Und ich liebe es, dass Sie semantisches HTML verwendet und Barrierefreiheit von Anfang an berücksichtigt haben.
In den HTML-Beispielen sollte es heißen
style="grid-column: track-1-start / track-1-end;"anstelle von
style=„grid-column: track-1;“`?
Gute Frage, Stu! Ich muss zugeben, dass Sie definitiv eine Inkonsistenz zwischen der Demo und dem Code im Artikel entdeckt haben; der Code im Artikel funktioniert jedoch. Ich habe die Demo entsprechend aktualisiert. Nun zur Frage, warum er funktioniert...
Dank Rachel Andrew habe ich bereits eine Antwort!
Ich werde versuchen, hier eine Zusammenfassung zu geben, aber schauen Sie sich ihren Artikel an, der es erklärt.
Wie in der Spezifikation beschrieben
Es ist also ein bisschen verwirrend, aber wir verwenden einen impliziten Grid-Liniennamen, der von einer impliziten Grid-Fläche generiert wird!
Die Jury ist sich noch nicht einig, ob das eine gute Idee ist (was meinen Sie?), aber es ist sicherlich prägnanter.
Toller Blog, um das Konzept des Grid-Systems zu verstehen. Ich werde dieses Konzept auf meiner Website implementieren.
Toller Artikel, Mark. Wir wurden auch vor ein paar Tagen gebeten, einen Event-Zeitplan zu erstellen, und dieser Artikel hat mich inspiriert, ein paar Notizen auf unserem Blog zu veröffentlichen. Wir haben sowohl CSS Grid als auch HTML-Tabellen untersucht und uns aufgrund der tabellarischen Daten, der Barrierefreiheit und der Browserkompatibilität für Tabellen entschieden – das waren die Schlüsselfaktoren.
https://www.liquidlight.co.uk/blog/create-an-event-schedule-with-html-table
Interessant zu sehen, dass Sie sich für Tabellen entschieden haben, João. Es ist auch cool zu sehen, dass Sie fast genau die gleiche Grid-Syntax verwenden! Dieser Artikel war zu lang, um auf Tabellenalternativen einzugehen, aber ich werde zwei Dinge sagen:
Sowohl mit Grid als auch mit Tabellen halte ich es für sinnvoll, die Zeiten direkt im Markup mit jeder Sitzung/jedem Event einzufügen.
Wunderbare Anwendung von Grid, regt wirklich die Gedanken an. Eine weitere coole Anwendung könnten Flugzeugsitze sein, etwas, woran ich vor ein paar Jahren gearbeitet habe und das über JavaScript gelöst wurde.
Wow, das ist eine Killer-Anwendung von Grid. Ich erinnere mich, wie ich ein solches Programm mit Tabellen gestaltet habe und es war elend!
Wir haben diese Technik Anfang dieses Jahres auf der Mauritius Developers Conference Website verwendet
https://2019.mscc.mu/sessions
Dies war ein Experiment ohne echte Referenzen, daher ist es wirklich cool, ein ähnliches Muster in Ihren Beispielen zu sehen!
https://github.com/mscraftsman/devcon2019/blob/master/web/app/src/views/PageSessions.vue#L488
Für die responsive Version haben wir, da wir VueJS verwendeten, jede Spalte wischbar gemacht.
Sehr cool, jetzt zwei weitere Leute sehr ähnliche Syntax mit den benannten Grid-Linien verwenden zu sehen! Ein interessanter Unterschied ist, dass ich sehe, dass Sie die
span-Syntax anstelle der Definition vongrid-row-endverwendet haben. Beides scheint mir aber gut zu sein :) Danke für das Teilen.Dieser Artikel hat mich inspiriert, einen vollständig anpassbaren Kalender zu erstellen
https://github.com/fabiogiolito/CSSGridCalendar
Sehr cool, Fabio. Es sieht großartig aus! Stellen Sie sicher, dass Sie an die Barrierefreiheit denken, insbesondere an das HTML.
Hallo Mark Root-Wiley, vielen Dank für den großartigen Artikel!
Ich möchte Sie um Erlaubnis bitten, diesen Artikel ins Koreanische zu übersetzen und auf einem von einem Unternehmen geführten Blog (https://ui.toast.com/) und auf unserer Github-Wiki-Seite (https://github.com/nhn/fe.javascript) zu veröffentlichen. Ich werde die Originalquelle zitieren und sie in keiner Weise zu Geldzwecken verwenden.
Bitte lassen Sie mich wissen, was Sie denken, und ich wünsche Ihnen einen schönen Tag :)
Von mir aus kein Problem, Jenny, aber Sie sollten die CSS Tricks-Richtlinien prüfen, da es nicht meine Seite ist. Danke für die Nachfrage, und ich vertraue darauf, dass Sie die Namensnennung angemessen handhaben werden.
Ich denke, CSS Tricks ist lizenziert. Aber es scheint nicht für den Artikel zu gelten. Und CSS Tricks scheint keine formelle Antwort zu geben.
Außerdem, da das Urheberrecht bei Ihnen liegt, würden wir Ihren Artikel gerne übersetzen, wenn Sie eine Entscheidung treffen.
Danke.
Das ist ein großartiger Artikel für den Aufbau eines Konferenzzeitplans.
Wenn sich ein Slot mit einem anderen überschneidet, sollte dies klar erkennbar sein, wie alle Events, die responsiv innerhalb des übergeordneten Divs sind, also was können wir tun?