Abschnitt 9 · Lektion 7
Synthese: die Kopfzeile
Erste Synthese des Abschnitts. Hier kommt kein neuer Wert dazu, hier wird zusammengesetzt: die klebende Kopfzeile aus 8.5, justify-content aus 9.3, align-items aus 9.4, gap aus 9.5 und der Fokusring aus 7.3.
Warum zwei Container besser sind als einer
<p class="titel">alles in einem Container: fünf Kinder, vier Lücken</p>
<header class="kopf flach">
<a class="logo" href="#">Mario</a>
<a href="#">Start</a>
<a href="#">Projekte</a>
<a href="#">Über mich</a>
<a href="#">Kontakt</a>
</header>
<p class="titel">verschachtelt: zwei Kinder außen, vier innen</p>
<header class="kopf tief">
<a class="logo" href="#">Mario</a>
<nav>
<ul>
<li><a href="#">Start</a></li>
<li><a href="#">Projekte</a></li>
<li><a href="#">Über mich</a></li>
<li><a href="#">Kontakt</a></li>
</ul>
</nav>
</header> body {
font-family: system-ui, sans-serif;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.kopf {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 12px 20px;
background-color: #18181b;
}
.kopf a {
color: #ffffff;
text-decoration-line: none;
}
.logo {
font-size: 20px;
font-weight: 700;
}
/* Oben zerstreut space-between alle fünf Kinder über
die ganze Breite. Unten sind es nur zwei Kinder,
und die Navigation bleibt als Block zusammen. */
.tief ul {
display: flex;
gap: 24px;
margin: 0;
padding: 0;
list-style-type: none;
} Der erste Versuch sieht meistens so aus: Logo und alle Links in eine Kopfzeile, display: flex, justify-content: space-between, fertig. Und dann liegt das Ergebnis daneben, weil space-between alle Lücken gleich behandelt. Bei fünf Kindern sind es vier Lücken, und die Navigation zerfällt über die ganze Breite.
Die Lösung ist keine andere Eigenschaft, sondern eine Ebene mehr. Außen hat die Kopfzeile genau zwei Kinder: das Logo und das nav. Dazwischen liegt genau eine Lücke, und space-between schiebt sie an die Ränder. Innen ist die Liste ein eigener Flex-Container, der seine vier Links mit gap gleichmäßig setzt.
Das ist die Regel aus 9.1 in ihrer nützlichen Form: Jeder Container verteilt nur seine direkten Kinder. Wenn ein Layout sich mit einer Ebene nicht sauber beschreiben lässt, ist meistens nicht die Eigenschaft falsch, sondern die Verschachtelung zu flach.
Das Markup dafür hast du im HTML-Kurs schon gebaut: nav mit einer ul darin, ein li pro Link. Das ist kein Umweg für die Optik, sondern das, was ein Screenreader als “Navigation mit vier Einträgen” ansagt.
Die Kopfzeile, die oben bleibt
<header class="kopf ohne">ohne top: klebt nie</header>
<p>Scroll den Kasten hier durch.</p>
<div class="fueller">Inhalt</div>
<header class="kopf mit">mit top: 0: klebt oben</header>
<p>Und hier auch.</p>
<div class="fueller">Inhalt</div> body {
margin: 0;
font-family: system-ui, sans-serif;
}
.kopf {
padding: 12px 16px;
font-weight: 700;
color: #ffffff;
background-color: #18181b;
}
.fueller {
height: 400px;
padding: 16px;
background-color: #f4f4f5;
}
/* Beide sind sticky. Die obere hat keine Schwelle
und läuft deshalb einfach mit nach oben weg. Es
gibt keine Fehlermeldung, die Angabe steht
gültig da und tut nichts. */
.ohne {
position: sticky;
}
.mit {
position: sticky;
top: 0;
} position: sticky aus 8.5, kurz aufgefrischt, weil hier der häufigste Fehler wartet: ohne Schwelle klebt nichts. position: sticky allein ist eine gültige Deklaration ohne Wirkung. Erst top: 0 sagt dem Browser, ab wann.
Im Beispiel steht zweimal dasselbe, einmal mit und einmal ohne top. Die obere Kopfzeile scrollt weg, obwohl an ihr ein sticky steht. Es gibt keine Meldung, es passiert einfach nichts, und man sucht den Fehler im Elternteil.
Ein z-index braucht die Kopfzeile hier übrigens nicht. Positionierte Elemente werden über nicht positionierten gezeichnet, und alles, was darunter scrollt, ist statisch. Sobald du unter ihr etwas positionierst, ändert sich das, und dann kommst du auf 8.6 zurück.
Der Fokusring gehört dazu
<p class="titel">outline: none, und die Tastatur ist blind</p>
<nav class="menue ohne">
<a href="#">Start</a>
<a href="#">Projekte</a>
<a href="#">Kontakt</a>
</nav>
<p class="titel">focus-visible mit Abstand vom Rand</p>
<nav class="menue mit">
<a href="#">Start</a>
<a href="#">Projekte</a>
<a href="#">Kontakt</a>
</nav>
<p class="hinweis">
Klick in die Seite und wander mit der Tabulatortaste durch beide
Menüs. Oben siehst du nicht, wo du bist.
</p> body {
font-family: system-ui, sans-serif;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.menue {
display: flex;
gap: 24px;
margin-bottom: 20px;
padding: 12px 16px;
background-color: #18181b;
}
.menue a {
color: #ffffff;
text-decoration-line: none;
}
/* So bitte nicht. Der Ring verschwindet für alle,
auch für die, die ihn brauchen. */
.ohne a:focus {
outline: none;
}
/* focus-visible zeigt ihn nur bei Tastaturbedienung,
und outline-offset schiebt ihn vom dunklen Rand weg,
damit man ihn überhaupt sieht. */
.mit a:focus-visible {
outline: 3px solid #60a5fa;
outline-offset: 4px;
} Eine Kopfzeile ist der erste Ort, an dem jemand mit der Tastatur ankommt. Deshalb gehört zu dieser Lektion die Zeile, die man in fremden Stylesheets am häufigsten falsch findet: outline: none.
Der Browser bringt einen Fokusring mit. Er sieht auf einer dunklen Kopfzeile oft schlecht aus, und dann wird er entfernt statt ersetzt. Das Ergebnis ist eine Navigation, die man mit der Maus bedienen kann und mit der Tastatur nicht mehr, weil man nicht sieht, wo man ist.
Der Ersatz kostet drei Zeilen: :focus-visible statt :focus, damit der Ring bei Mausklicks wegbleibt und bei der Tabulatortaste erscheint, dazu ein outline-offset, der ihn vom Rand wegschiebt.
Denk daran, wenn du gleich baust. Geprüft wird der Ring nicht, weil die Probe keinen Fokus simulieren kann. Fehlen darf er trotzdem nicht.
Zum Mitnehmen
Zwei Flex-Container statt einem. Außen die Kopfzeile mit zwei Blöcken, innen die Liste mit ihren Links. Ein einziger Container müsste jeden Link einzeln gegen das Logo ausbalancieren, und genau daran scheitern die meisten ersten Versuche.
Jetzt du
Basis Konto, kostenlosZu 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.