Einen Konferenzzeitplan mit CSS Grid erstellen

Avatar of Mark Root-Wiley
Mark Root-Wiley am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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.

A schedule with 4 tracks of presentations (columns) and 6 times slots. The length of sessions vary, and some talks span multiple tracks.
Das endgültige Layout, das wir erstellen werden.

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

Personen auf Smartphones, die ihre Browser vergrößern, oder sogar Internet Explorer-Nutzer werden keine Probleme haben, ihre Lieblingssitzungen auf dieser Konferenz zu finden!

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.

A 5 row grid with numbered lines, 1-6.
Eine rudimentäre Version eines einzelnen Spaltenzeitplans mit nummerierten Gridlinien. (Demo ansehen: Nummerierte Gridlinien vs. Benannte Gridlinien)
.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.

A 5 row grid with rows named for the time. Example: time-0800
Durch die Verwendung benannter Grid-Linien für den Zeitplan wird es viel einfacher, eine Sitzung zu platzieren. (Demo ansehen: Nummerierte Gridlinien vs. Benannte Gridlinien)
.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.

A grid with 5 rows of equal height. The height matches the tallest row containing 3 lines of text.
Verwendung von 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.

A grid with 5 rows of unequal height. Each row contains its content.
Verwendung von 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?**