mitmario.dev

Synthese: die halbe Startseite

CSS Im Browser 3 Min Lesezeit 3 BeispieleLektion 4 von 5

Ab hier kippt der Kurs. Bis jetzt stand in jeder Lektion eine Eigenschaft im Vordergrund, ab jetzt steht eine Seite im Vordergrund und die Eigenschaften sind das Werkzeug.

Die Reihenfolge

Es gibt eine Reihenfolge, in der man eine Seite baut, und sie ist von außen nach innen:

  1. Das äußere Layout. Wie sind die großen Blöcke angeordnet? Kopf, Inhalt, Fuß, vielleicht eine Seitenspalte.
  2. Die Bereiche. Was passiert innerhalb eines Blocks? Der Hero bekommt sein Bild, der Inhaltsbereich sein Raster.
  3. Die Komponenten. Wie sieht eine einzelne Karte aus?
  4. Die Details. Zustände, Abstände nachjustieren, Fokusringe.

Warum nicht mit der Karte anfangen

Die Karte zuerst gebaut
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

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

.projekte {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 16px;
}

/* Die Breite stammt aus der Zeit, als die Karte allein
   auf der Seite stand. Im Raster wird sie zur Untergrenze
   der Spur, und drei davon passen nicht mehr nebeneinander. */
.projekt {
  width: 320px;
  padding: 20px;
  border-radius: 12px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

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

Der naheliegende Weg ist der umgekehrte: Man baut erst die schöne Karte, weil sie das ist, was man sich vorstellt, und legt sie danach in ein Raster.

Dabei passiert zuverlässig das hier: Die Karte bekommt eine Breite, denn sie steht ja allein auf der Seite und muss irgendwie aufhören. Im Raster steht diese Breite dann im Weg, und zwar anders, als man erwartet. 1fr heißt ausgeschrieben minmax(auto, 1fr), und das auto darin ist die automatische Mindestgröße der Spur. Bei einem Item mit fester Breite ist das genau diese Breite. Die Spur wird also nicht schmaler als die Karte, sondern das Raster wird breiter als die Seite: dreimal 320 Pixel plus zwei Lücken sind 992, und im Beispiel ist die dritte Karte rechts abgeschnitten.

Im Streifen stehen die beiden Zahlen fast untereinander. Geh ins Vollbild, dort steht die Seite von allein auf den 900 aus der Vorgabe, und zeig dann auf das Raster: width: 884px, ein paar Zeilen tiefer grid-template-columns: 320px 320px 320px. Der Container ist 884 breit, seine drei Spuren sind zusammen 992, und die Differenz ist genau das Stück, das rechts fehlt. Aus repeat(3, 1fr) ist dabei dreimal die Kartenbreite geworden, obwohl an keiner Spur 320px steht.

Soll die Spur wirklich schmaler werden dürfen als ihr Inhalt, ist minmax(0, 1fr) der Hebel. Das räumt den Überlauf des Rasters weg, den Widerspruch aber nicht: die Karte behauptet weiter 320 Pixel und ragt dann eben aus ihrer Spur.

Jetzt hast du zwei Stellen, die dasselbe behaupten, und musst dich entscheiden, welche gewinnt. Das ist genau der Zustand, den Abschnitt 3 als Stilkonflikt beschrieben hat, nur selbst gebaut.

Was eine Komponente über sich wissen darf

Von außen nach innen
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

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

.projekte {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 16px;
}

/* Innenabstand, Ecken, Farben: alles, was die Karte
   über sich selbst weiß. Keine Breite. */
.projekt {
  padding: 20px;
  border-radius: 12px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

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

Daraus wird eine Regel, die weit über diese Lektion hinausreicht:

Eine Komponente beschreibt, wie sie innen aussieht. Wie breit sie ist, entscheidet der Ort, an dem sie steht.

Dieselbe Messung am zweiten Beispiel: Dort ist jede Karte 284 breit, dreimal 284 plus zwei Lücken sind 884, also genau die Breite des Rasters. Nicht weil jemand 284 hingeschrieben hätte, sondern weil niemand etwas hingeschrieben hat.

Innenabstand, Ecken, Farben, Schrift: das gehört der Karte. Breite, Position und Abstand zu ihren Nachbarn: das gehört dem Container. Eine Karte, die sich daran hält, passt in ein dreispaltiges Raster, in eine schmale Seitenspalte und in eine einspaltige Ansicht auf dem Handy, ohne dass an ihr etwas geändert wird.

Denselben Gedanken hattest du schon zweimal: bei gap in 9.5 (“der Abstand gehört an den Container”) und beim Kartenraster in 10.2 (“das Raster kennt seine eigene Breite”).

Tokens und die Zahlen, die bleiben dürfen

Tokens statt verstreuter Zahlen
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Die Tokens aus Lektion 5.5. Sie stehen einmal oben
   und gelten überall. Für den Dunkelmodus in 12.6
   werden genau diese vier Zeilen umgeschaltet. */
:root {
  --farbe-text: #18181b;
  --farbe-flaeche: #ffffff;
  --farbe-akzent: #2563eb;
  --abstand-m: 16px;
  --abstand-l: 24px;
  --radius-m: 12px;
}

body {
  padding: var(--abstand-l);
  font-family: system-ui, sans-serif;
  line-height: 1.5;
  color: var(--farbe-text);
  background-color: #f4f4f5;
}

.karte {
  max-width: 360px;
  padding: var(--abstand-l);
  border-radius: var(--radius-m);
  background-color: var(--farbe-flaeche);
}

.karte h3 {
  margin: 0 0 4px 0;
}

.karte p {
  margin: 0 0 var(--abstand-m) 0;
  color: #52525b;
}

/* Und hier eine feste Zahl, die genau so bleiben darf:
   999px ist kein Maß, sondern die Ansage rund. Ein
   Token dafür würde nur so tun, als wäre es eines. */
.knopf {
  display: inline-block;
  padding: 8px var(--abstand-m);
  border-radius: 999px;
  font-weight: 700;
  text-decoration-line: none;
  color: #ffffff;
  background-color: var(--farbe-akzent);
}

Die Tokens aus Lektion 5.5 zahlen sich ab jetzt aus. Farben, Abstände und Radien stehen einmal oben und gelten überall, und im Dunkelmodus in 12.6 werden genau diese Zeilen umgeschaltet statt jeder einzelnen Regel.

Nicht jede Zahl muss aber ein Token werden. Die Faustregel: Ein Token ist eine Entscheidung, die an mehreren Stellen dieselbe sein soll. Der Radius einer Karte ist so eine. Die 999px am runden Knopf sind keine, denn das ist kein Maß, sondern die Ansage “mach ihn rund”. Ein --radius-rund: 999px würde nur so tun, als könnte man daran etwas drehen.

Genauso bleiben Zahlen frei, die aus einer Rechnung kommen: die Zeilenlänge in ch, eine minmax-Untergrenze, ein z-index. Ein Token dafür macht den Wert nicht flexibler, nur weiter weg von der Stelle, an der man ihn versteht.

Zum Mitnehmen

Erst das äußere Layout, dann die Bereiche, dann die Komponenten, zuletzt die Details. Wer mit der Karte anfängt, gibt ihr eine Breite, die zum Raster nicht passt, und baut sie zweimal.

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 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.