Was macht layout?
Dieser Skill entscheidet, wo Dinge platziert werden, wie weit sie voneinander entfernt sind und wie groß sie sind. Er trifft dieselben Entscheidungen in derselben Reihenfolge und überprüft das Ergebnis an den gerenderten Pixeln.
Vor jeder Entscheidung wende product-ui §1 (das Geschmacksjournal und die Rangfolge) und §5 (welcher Skill was besitzt) an.
Entscheide in dieser Reihenfolge
- Shell. Benenne die Bildschirmbereiche: Sidebar, Toolbar, Content, Inspector. Jeder Bereich ist ein Scroll-Eigentümer oder keiner. Details und Breiten: shell-and-responsive.md. Warum: Die Shell legt jede Breite fest, in der das innere Layout leben muss.
- Breite und Maß. Setze die Inhaltsbreite je nach Inhalt: Formular 440px, Lesemodus 720px mit einer auf das
type-Maß (66ch) begrenzten Prosa, Daten 1200px. Eine Spalte dehnt sich nie, weil der Bildschirm breit ist. Warum: Ab 75 Zeichen verliert eine Zeile den Leser, und ein gestrecktes Formular schickt die Augen über den Bildschirm. - Abstand. Verwende ausschließlich die untenstehende Skala. Gruppiere zuerst mit Abstand; füge eine Füllung hinzu, dann eine Linie, nur dort, wo Abstand es nicht tragen kann. spacing-and-density.md.
- Ausrichten. Wähle die gemeinsamen Kanten und platziere alles daran. Ein Fehler von 1–4 Pixeln ist ein Bug. Korrigiere optisch, wo die Geometrie falsch aussieht. spacing-and-density.md.
- Größe. Wähle die Dichte für den Bereich, dann die Trefferflächen. spacing-and-density.md.
- Schlimmstfall-Daten. Ändere die Größe der Box für den längsten, kürzesten, fehlenden, übersetzten und noch ladenden Inhalt, bevor du sie als erledigt betrachtest. stability-and-text.md.
- Anpassen. Lass die Struktur auf ihren Container reagieren, nicht auf das Gerät. shell-and-responsive.md.
- Messen. Rendere in 2×, messe Lücken und Kanten, korrigiere, was die Pixel zeigen. measure.md.
Die Skala
Eine Skala, 4px Basis. Schreibe niemals einen Abstandswert, der kein Schritt ist. Warum: Einzelwerte (10px, 14px, 18px) machen Rhythmus unsichtbar und unmöglich zu erhalten.
| Token | px | Typische Verwendung |
|---|---|---|
--space-xs | 4 | Label zu seiner Beschreibung; Icon zu Label in einem Chip |
--space-sm | 8 | Elemente innerhalb einer Gruppe; Steuerelement-Padding block |
--space-md | 12 | Zwischen umrandeten Steuerelementen; Steuerelement-Padding inline |
--space-lg | 16 | Zwischen Feldern; kompaktes Karten-Padding |
--space-20 | 20 | Zwischen Blöcken innerhalb einer Karte |
--space-xl | 24 | Zwischen Gruppen; luftiges Karten-Padding |
--space-2xl | 32 | Zwischen Abschnitten |
--space-3xl | 48 | Über dem ersten Titel einer Seite |
--space-4xl | 64 | Unter dem letzten Block einer Seite |
1–2px Korrekturen für optische Ausrichtung sind die einzigen Werte außerhalb der Skala. Benenne sie (--play-nudge: 2px).
Regeln, die keine Referenz benötigen
- Gruppiere mit Abstand. Der Abstand zwischen Gruppen ist mindestens das 2-fache des Abstands innerhalb einer Gruppe: 8px innen bedeuten 16px oder mehr außen. Gleiche Abstände überall machen die Gruppierung mehrdeutig, und Mehrdeutigkeit ist hier ein funktionaler Bug.
- Entferne Linien, bevor du sie hinzufügst. Zuerst Abstand, dann eine Füllung, zuletzt eine Trennlinie, und nur für dichte Daten. Warum: Jede Linie kostet Aufmerksamkeit für dieselbe Information, die Abstand kostenlos gibt.
- Abstand oben entspricht Abstand unten für alles, was zwischen zwei Dingen steht. Warum: Ein Ding, das näher an einem Nachbarn ist, wirkt als ob es ihm gehört.
- Steuerelemente müssen wie Steuerelemente aussehen. Ein Button, Link oder Toggle hat eine Form, eine Unterstreichung oder eine Toolbar-Position. Statischer Text teilt diese niemals. Warum: Ein wie Text gestyltes Steuerelement versteckt sich, und ein wie ein Steuerelement gestylter Text sammelt tote Klicks.
- Aktionen stehen über den Daten, auf die sie wirken, niemals darunter. Ein Steuerelement, das etwas setzt, steht daneben.
- Primärer Inhalt kommt zuerst und führend. Visuelle Reihenfolge entspricht der DOM-Reihenfolge: niemals
order,row-reverseoder Grid-Platzierung, um Inhalt umzuordnen. Warum: Die Tastatur- und Screenreader-Reihenfolge folgt dem DOM. - Logische Eigenschaften (
margin-inline-start,padding-block,inset-inline-end,text-align: start) für alles, was gespiegelt wird. Warum: RTL funktioniert dann ohne zweites Stylesheet. - Setze niemals kritische Steuerelemente an den unteren Rand eines Fensters oder einer Sidebar. Warum: Menschen schieben Fenster teilweise aus dem Bildschirm.
- Scrollen zeigt, was verborgen ist. Inhalt hinter einer Kante erhält einen sichtbaren Hinweis: einen Einblick von 16–32px oder eine Einblendung.
- Nichts verschiebt sich. Hover, Auswahl und Fokus ändern niemals die Größe eines Elements. Geladene Daten nehmen die Box ein, die das Skelett hatte.
Paare
| Kaputt | Korrigiert | Warum |
|---|---|---|
gap: 12px im Formular und gap: 12px zwischen seinen Fieldsets | gap: 8px innen, gap: 24px zwischen | Gruppen brauchen einen Abstand von mindestens 2× |
padding: 10px 14px | padding: var(--space-sm) var(--space-md) | Nur Schritte |
| Titel bei x=24, Beschreibung bei x=26 | Beide bei x=24 | Ein Fehler von 1–4px wirkt wie ein Fehler |
Icon-Button 16×16 mit padding: 0 | 16px Glyphe, ::before { inset: -12px } für ein 40px Ziel | Mausziel ist 40px |
.row + .row { margin-top: 8px } mit Hover und Klick auf Zeilen | .row { padding-block: 4px }, kein margin | Ein Abstand zwischen Zeilen ist eine tote Zone und lässt Hover flackern |
.menu { width: 200px } | width: max-content; min-width: 160px; max-width: 320px | Das Menü umschließt sein längstes Label |
@media (max-width: 768px) auf einer Karte | @container (width < 400px) auf dem Eltern-Element der Karte | Eine Karte in einer schmalen Sidebar braucht ihre eigene Breite, nicht die des Bildschirms |
<img src> ohne Größe, dann eine Karte, die springt | width, height oder aspect-ratio gesetzt | Die Box existiert vor den Bytes |
| Sticky-Header, Anker landet darunter | scroll-padding-block-start: 56px auf dem Scroller | Fokus und Anker liegen nie unter Chrome |
Bevor du fertig bist
Durchsuche das Diff nach diesen Mustern und überprüfe sie dann.
| Muster | Korrektur |
|---|---|
margin, padding oder gap mit einem Wert, der nicht in der Skala ist | Nächster Schritt |
Ein gap-Wert innerhalb und zwischen Gruppen verwendet | Innen ≤ Hälfte von außen |
Icon-Button unter 24px oder unter 40px ohne ::before | Mit einem Pseudo-Element erweitern |
gap oder margin zwischen klickbaren Zeilen oder Menüeinträgen | Padding innerhalb des Elements |
Feste width bei einem Menü, Button oder Textfeld | max-content, min-width, max-width; min-height für Text |
@media (max-width innerhalb einer wiederverwendbaren Komponente | @container auf ihrem Eltern-Element |
height: 100vh für eine Shell | 100dvh |
1fr-Track oder Flex-Kind, das langen Text hält | minmax(0, 1fr) oder min-width: 0 |
margin-left, padding-right, left: 0, text-align: left in gespiegelter UI | Logische Form |
Sticky-Header oder -Footer ohne scroll-padding-block | Auf die Höhe des Chrome setzen |
| Skelett-Zeilen- oder Spaltenbreiten unterscheiden sich von geladenen | Angleichen |
<img> ohne Maße oder aspect-ratio | Eine hinzufügen |
Überprüfe mit measure.md: rendere in 2× bei 390px und der breitesten Breite der Shell, führe das Skript aus, beschneide jeden Kandidaten und zähle Pixel. Tabben dich dann mit klebrigem Chrome durch den Bildschirm und lade die längsten Zeichenketten. Melde, was du nicht überprüfen konntest, als „nicht verifiziert“.