mitmario.dev

Die halbe Startseite

CSS Im Browser 3 Min Lesezeit 3 BeispieleLektion 4 von 5

Eine Seite aus Kopfzeile, Hero und drei Projektkarten braucht keine neue Eigenschaft, aber eine Reihenfolge. Diesmal steht die Seite im Vordergrund, und die Eigenschaften, die du kennst, sind nur das Werkzeug.

Die Reihenfolge

Gebaut wird von außen nach innen.

  1. Das äußere Layout. Wie sind die großen Blöcke angeordnet? Kopfzeile, Inhalt, Fußzeile, 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: 24px;
  border-radius: 12px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

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

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

Die Karte bekommt dabei eine Breite, denn sie steht allein auf der Seite und muss irgendwo 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 Kind 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 beide Zahlen. Im Vollbild steht die Seite von allein auf den 900 aus der Vorgabe, und am Raster steht dort width: 884px und weiter unten 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. Damit ist der Überlauf des Rasters weg, der Widerspruch aber nicht. Die Karte behauptet weiter 320 Pixel und ragt dann eben aus ihrer Spur.

Dann stehen zwei Stellen da, die dasselbe behaupten, und eine muss gewinnen. Das ist der Stilkonflikt aus Abschnitt 3, nur diesmal 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: 24px;
  border-radius: 12px;
  font-weight: 700;
  color: #ffffff;
  background-color: #2563eb;
}

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

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

Im zweiten Beispiel ist jede Karte 284 breit. Dreimal 284 plus zwei Lücken sind 884, also die Breite des Rasters. Hingeschrieben hat die 284 niemand, sie bleibt übrig, weil an der Karte keine Breite steht.

Innenabstand, Ecken, Farben und Schrift gehören der Karte. Breite, Position und Abstand zu den Nachbarn gehören 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, und an ihr selbst musst du dafür nichts ändern.

Den Gedanken gab es schon zweimal. Bei gap in 9.5 gehörte der Abstand an den Container, und das Kartenraster in 10.8 kannte seine eigene Breite.

Tokens und die Zahlen, die bleiben dürfen

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

/* Ein Ausschnitt der Tokens aus Lektion 5.5. Für den
   Dunkelmodus in 12.6 bekommen die Farbrollen darin
   je einen zweiten Wert, die Regeln bleiben. */
:root {
  --abstand-xs: 4px;
  --abstand-s: 8px;
  --abstand-l: 24px;
  --radius-m: 12px;
  --schrift-s: 14px;
  --farbe-text: #18181b;
  --farbe-gedaempft: #52525b;
  --farbe-flaeche: #ffffff;
  --farbe-grund: #f4f4f5;
  --farbe-akzent: #2563eb;
  --farbe-auf-dunkel: #fafafa;
}

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

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

.karte h3 {
  margin: var(--abstand-s) 0 var(--abstand-xs) 0;
}

.karte p {
  margin: 0;
  color: var(--farbe-gedaempft);
}

/* 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. */
.badge {
  padding: var(--abstand-xs) var(--abstand-s);
  border-radius: 999px;
  font-size: var(--schrift-s);
  color: var(--farbe-auf-dunkel);
  background-color: var(--farbe-akzent);
}

Ab jetzt zahlen sich die Tokens aus Abschnitt 5 aus. Farben, Abstände und Radien stehen einmal oben und gelten überall. Im Dunkelmodus schaltest du später diese Zeilen um und nicht jede einzelne Regel.

Nicht jede Zahl muss aber ein Token werden. Ein Token ist eine Entscheidung, die an mehreren Stellen dieselbe sein soll. Der Radius einer Karte ist so eine. Die 999px am runden Badge 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, etwa die Zeilenlänge in ch, eine minmax-Untergrenze oder ein z-index. Ein Token macht so einen Wert nicht flexibler. Er steht dann nur weiter weg von der Stelle, an der man ihn versteht.

In der Aufgabe ist die Karte zuerst gebaut worden, und um sie herum fehlt das Layout.

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.