mitmario.dev

Ein Raster von Hand

CSS Im Browser 4 Min Lesezeit 4 BeispieleLektion 3 von 5

Zwölf-Spalten-Raster kennt man aus Bootstrap und seinen Verwandten. Eines nachzubauen dauert ungefähr so lange, wie ein Framework einzubinden.

Das ganze Raster

Zwölf Spalten, zwei Zeilen CSS
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, sans-serif;
}

/* Das ganze Raster. Mehr braucht es nicht. */
.raster {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 8px;
}

.block {
  padding: 16px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

/* Und je Block eine Zeile. Die Zahl dahinter ist die
   Zahl der Spalten, die er überdeckt. */
.s12 { grid-column: span 12; }
.s8 { grid-column: span 8; }
.s6 { grid-column: span 6; }
.s4 { grid-column: span 4; }
.s3 { grid-column: span 3; }

Am Container stehen zwei Zeilen, display: grid und grid-template-columns: repeat(12, 1fr). Dazu kommt ein gap, damit die Blöcke nicht aneinanderkleben.

An jedem Block steht eine Zeile, etwa grid-column: span 8, und die überdeckt acht der zwölf Spuren.

Was daraus wird, steht im Inspector. Fährst du in eine Lücke zwischen zwei Blöcken, liegt der Container selbst unter dem Zeiger. Im Auskunftsstreifen steht dann hinter grid-template-columns eine Reihe von zwölf Zahlen, bei der Breite, mit der die Spalte startet, zwölfmal 23px. Aus einer Zeile mit repeat werden zwölf Spuren, und im Streifen stehen sie einzeln da.

Spannender sind die Blöcke darin. span 8 misst 240, span 4 misst 116. Das Doppelte von 116 wären 232, und die fehlenden acht Pixel sind die Lücke, denn bei span 8 liegt eine davon mitten im Block und zählt mit. Ein Block über acht Spalten ist so breit wie zwei Blöcke über vier plus die Lücke dazwischen. Die Lücken gehören keiner Spur, und beim Rechnen ist das der Punkt, an dem man sich vertut.

So nicht, bis Linie 12
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, sans-serif;
}

.titel {
  margin-bottom: 4px;
  font-size: 14px;
  color: #52525b;
}

/* Grau ist das Raster selbst, damit eine leere Spur
   zu sehen ist. */
.raster {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 8px;
  margin-bottom: 24px;
  background-color: #e4e4e7;
}

.block {
  padding: 16px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

/* Zwölf Spalten haben dreizehn Linien. Wer bei Linie
   12 aufhört, deckt nur elf. */
.bis-zwoelf {
  grid-column: 1 / 12;
}

.bis-dreizehn {
  grid-column: 1 / 13;
}

Der zweite Punkt sind die Linien. Zwölf Spalten haben dreizehn Linien, die erste vor der ersten Spalte und die letzte hinter der zwölften. Wenn du einen Block mit grid-column: 1 / 12 über die ganze Breite legen willst, hört er eine Spalte zu früh auf. Im Beispiel bleibt oben rechts eine graue Fläche frei, bei der Breite, mit der die Spalte startet, 31 Pixel, also eine Spur und eine Lücke. Der Block misst dort 333, der darunter mit 1 / 13 die vollen 364.

Das ist alles. Kein Container-Wrapper, keine Zeilen-Elemente, keine negativen Außenabstände, mit denen der Randabstand wieder herausgerechnet wird. All das war nötig, als man Raster mit float gebaut hat, und in älteren Frameworks steckt es bis heute drin.

Benennst du die Klassen wie im Beispiel, hast du dir nebenbei ein eigenes Mini-Framework gebaut. Fünf Zeilen für die fünf Breiten, die du wirklich brauchst.

Warum ausgerechnet zwölf

Warum ausgerechnet zwölf
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, sans-serif;
}

.titel {
  margin-bottom: 4px;
  font-size: 14px;
  color: #52525b;
}

/* Zwölf teilt sich durch 2, 3, 4 und 6 ohne Rest.
   Bei zehn Spalten bliebe davon nur das Halbieren. */
.raster {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}

.block {
  padding: 16px;
  text-align: center;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

.s6 { grid-column: span 6; }
.s4 { grid-column: span 4; }
.s3 { grid-column: span 3; }
.s2 { grid-column: span 2; }

Zwölf lässt sich durch 2, 3, 4 und 6 teilen.

Damit kannst du dasselbe Raster halbieren, dritteln, vierteln und sechsteln, und nirgends entsteht eine krumme Zahl. Bei zehn Spalten bliebe von den vier Aufteilungen nur das Halbieren übrig, bei acht das Halbieren und das Vierteln.

Deshalb arbeitet auch Bootstrap, das bekannteste CSS-Framework, mit zwölf Spalten.

Fest oder selbstzählend

Feste Spaltenzahl gegen auto-fit
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

.titel {
  margin-bottom: 4px;
  font-size: 14px;
  color: #52525b;
}

.raster {
  display: grid;
  gap: 8px;
  margin-bottom: 16px;
}

/* Ich bestimme die Aufteilung. Gut für Seitenlayouts,
   bei denen das Verhältnis eine Entscheidung ist. */
.zwoelf {
  grid-template-columns: repeat(12, 1fr);
}

/* Der Platz bestimmt sie. Gut für Kartenlisten, bei
   denen niemand weiß, wie viele es werden. */
.automatisch {
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}

.block {
  padding: 16px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

.s8 { grid-column: span 8; }
.s4 { grid-column: span 4; }

.hinweis {
  max-width: 56ch;
  color: #52525b;
}

Es gibt zwei Sorten Raster, und sie beantworten verschiedene Fragen.

Bei einer festen Spaltenzahl bestimme ich die Aufteilung. Ein Hauptteil neben einer Seitenspalte im Verhältnis 8 zu 4 bleibt 8 zu 4, egal wie breit der Bildschirm ist. Das passt zu Seitenlayouts, bei denen das Verhältnis eine gestalterische Entscheidung ist. Ändern soll es sich nur dort, wo du es in einer Media Query ausdrücklich sagst, und das kommt im nächsten Abschnitt.

Bei auto-fit mit minmax() bestimmt der Platz die Spaltenzahl. Das passt zu Kartenlisten, bei denen niemand vorher weiß, wie viele Karten es werden und wie breit der Bereich ist.

Gebaut hast du beides schon in Abschnitt 10, neu ist nur, dass sie hier nebeneinanderstehen. Dahinter steckt dieselbe Frage wie in 11.1, nämlich ob ich es vorher weiß oder nicht.

Ziehst du die Spalte breiter oder schmaler, siehst du den Unterschied im Streifen an den Zahlen. Oben ändern sich nur die Maße. span 8 und span 4 messen in der schmalen Spalte 240 und 116, im Vollbild, das von allein auf 768 Pixeln steht, rund 499 und 245. Acht zu vier bleibt acht zu vier, in jeder Breite. Unten ändert sich die Anzahl. In der Spalte steht am Container grid-template-columns: 178px 178px, also zwei Spuren, und die dritte Karte rutscht in die zweite Zeile. Bei 768 misst jede Karte rund 245, und alle drei stehen nebeneinander.

Wann sich ein Framework doch lohnt

Seltener, als man denkt, aber nicht nie.

Ein Rastersystem ist der Teil eines Frameworks, den du am schnellsten selbst nachbaust. Daneben bringen Frameworks die Arbeit mit, die wirklich dauert, also fertige Komponenten, abgestimmte Farben, getestete Formularelemente und eine Dokumentation, an die sich ein ganzes Team halten kann. Wer das braucht, bekommt das Raster als Beigabe.

Brauchst du nur ein Raster, holst du dir mit dem Framework ein Stylesheet, ein Klassenschema und eine fremde Meinung über Abstände ins Projekt. Für die paar Zeilen aus dieser Lektion ist das ein schlechtes Geschäft.

Es gibt auch einen Zwischenweg, mit der Spurdefinition am Container und statt Klassen wie .s8 gleich sprechenden Namen. .inhalt { grid-column: span 8 } sagt dir in einem halben Jahr, warum der Block acht Spalten breit ist. .s8 sagt dir nur, dass er es ist.

In der Aufgabe stehen vier Blöcke untereinander, die in ein Zwölf-Spalten-Raster sollen.

Zum Mitnehmen

Ein Zwölf-Spalten-Raster ist repeat(12, 1fr) am Container und ein span je Block. Eine feste Spaltenzahl nimmt man, wenn das Verhältnis eine Entscheidung ist, auto-fit, wenn der Platz entscheiden soll.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 4 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.