Gutes Layout ist unsichtbar. Du merkst es nur, wenn es nicht funktioniert: Content springt, Elemente überlappen, Mobile ist kaputt.
Dieser Teil zeigt, wie du robustes, performantes Layout baust.
1. Flexbox-Fallen & Optimierungen
Die flex: 1 Falle
/* ❌ Problematisch */
.container {
display: flex;
}
.item {
flex: 1; /* flex: 1 1 0% */
}
Problem: flex: 1 bedeutet “Nimm allen verfügbaren Platz”. Browser muss bei jedem Resize alle Flex-Items neu berechnen.
Besser:
/* ✅ Feste Basis */
.item {
flex: 0 0 300px; /* Nicht wachsen/schrumpfen, 300px Basis */
}
/* ✅ Oder mit calc */
.item {
flex: 0 0 calc(33.333% - 1rem);
}
min-width: 0 für Text-Overflow
/* ❌ Text bricht nicht um */
.flex-item {
display: flex;
}
.text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Problem: Flex-Items haben min-width: auto → Text zwingt Item zu wachsen.
Lösung:
/* ✅ Erlaubt Schrumpfen */
.flex-item {
min-width: 0;
}
gap statt margin
/* ❌ Umständlich */
.item {
margin-right: 1rem;
}
.item:last-child {
margin-right: 0;
}
/* ✅ Sauber */
.container {
display: flex;
gap: 1rem;
}
justify-content vs. margin: auto
/* ✅ Beide OK, unterschiedlich */
/* Zentrierung */
.container {
display: flex;
justify-content: center;
}
/* Oder */
.item {
margin: 0 auto;
}
/* Abstand zwischen Items */
.container {
display: flex;
justify-content: space-between;
}
/* Letztes Item rechts */
.last-item {
margin-left: auto;
}
2. Grid für komplexe Layouts
Wann Grid statt Flex?
Flex: 1D (Zeile ODER Spalte) Grid: 2D (Zeilen UND Spalten)
/* ❌ Flex für 2D = kompliziert */
.gallery {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 0 0 calc(33.333% - 1rem);
margin: 0.5rem;
}
/* ✅ Grid = einfach */
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
auto-fit vs. auto-fill
/* auto-fit: Dehnt Items auf verfügbaren Platz */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
/* auto-fill: Behält Grid-Tracks, auch wenn leer */
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
Faustregel:
auto-fitfür Cards (dehnen OK)auto-fillfür feste Raster (leere Tracks OK)
Explicit vs. Implicit Grid
/* Explicit: Du definierst */
.grid {
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
}
/* Implicit: Browser erstellt bei Bedarf */
.grid {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px; /* Neue Rows = 200px */
}
Subgrid
/* Parent Grid */
.layout {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
}
/* Child übernimmt Parent-Spalten */
.card {
display: grid;
grid-column: span 4;
grid-template-columns: subgrid; /* Nutzt 12-Spalten des Parents */
}
Browser-Support: Seit 2023 in allen modernen Browsern.
Grid-Template-Areas (Semantic Grid)
.layout {
display: grid;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
Responsive:
@media (max-width: 768px) {
.layout {
grid-template-areas:
"header"
"main"
"sidebar"
"aside"
"footer";
grid-template-columns: 1fr;
}
}
3. Container Queries
Warum besser als Media Queries?
Media Query: “Wie groß ist der Viewport?” Container Query: “Wie groß ist der Container?”
/* ❌ Media Query - starr */
@media (max-width: 768px) {
.card {
flex-direction: column;
}
}
/* ✅ Container Query - flexibel */
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (max-width: 400px) {
.card {
flex-direction: column;
}
}
Vorteil: Card passt sich an Container-Größe an, nicht Viewport. Funktioniert in Sidebar UND Main-Area.
Container Types
/* inline-size: Nur Breite tracken */
.container {
container-type: inline-size;
}
/* size: Breite UND Höhe tracken */
.container {
container-type: size;
}
/* normal: Kein Container Query Support */
.container {
container-type: normal;
}
Performance: inline-size ist schneller als size.
Container Query Units
.card-container {
container-type: inline-size;
}
.title {
/* 5% der Container-Breite */
font-size: 5cqw;
/* 10% der Container-Höhe */
margin: 10cqh;
/* clamp mit Container Units */
font-size: clamp(1rem, 3cqw, 2rem);
}
Units:
cqw- Container Query Widthcqh- Container Query Heightcqi- Container Query Inlinecqb- Container Query Block
Komponenten-Responsiveness
/* Komponente passt sich selbst an */
.card {
container-type: inline-size;
padding: 1rem;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 150px 1fr;
gap: 1rem;
}
}
@container (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr 150px;
}
}
4. CLS & Layout Shift minimieren
CLS = Cumulative Layout Shift. Google Core Web Vital. Misst, wie viel Content beim Laden “springt”.
Platzhalter für Bilder
/* ❌ Kein Platz reserviert */
<img src="photo.jpg" alt="Photo" />
/* ✅ aspect-ratio reserviert Platz */
img {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
Noch besser mit HTML:
<img
src="photo.jpg"
width="800"
height="600"
alt="Photo"
/>
Browser berechnet aspect-ratio automatisch aus width/height.
Font Loading ohne Shift
/* ❌ Font lädt = Layout springt */
@font-face {
font-family: 'Custom';
src: url('custom.woff2');
}
/* ✅ Fallback mit ähnlichen Metriken */
@font-face {
font-family: 'Custom';
src: url('custom.woff2');
font-display: swap; /* Zeigt Fallback, dann wechselt */
size-adjust: 100%;
ascent-override: 90%;
descent-override: 25%;
}
body {
font-family: 'Custom', Arial, sans-serif;
}
Skeleton Screens
/* Skeleton während Laden */
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: 4px;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* Exakte Größe wie finaler Content */
.skeleton-title {
height: 2rem;
width: 60%;
margin-bottom: 1rem;
}
.skeleton-text {
height: 1rem;
width: 100%;
margin-bottom: 0.5rem;
}
Ads & Dynamic Content
/* ❌ Ad lädt = Content springt */
<div class="ad-slot"></div>
/* ✅ Feste Höhe reservieren */
.ad-slot {
min-height: 250px; /* Standard-Ad-Größe */
background: #f5f5f5;
}
Accordion & Collapsible
/* ❌ Instant Collapse = CLS */
.content {
display: none;
}
.content.open {
display: block;
}
/* ✅ Smooth Transition */
.content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.content.open {
max-height: 1000px; /* Größer als je nötig */
}
Noch besser mit Details:
<!-- Native Accordion, kein JS, kein CLS -->
<details>
<summary>Click me</summary>
<p>Content here</p>
</details>
KI-Audit: Layout & Responsiveness prüfen
Kopiere diesen Prompt in Claude, ChatGPT oder deine bevorzugte KI:
Analysiere mein Projekt auf Layout und Responsiveness-Probleme:
1. **Flexbox Overflow**: Finde Flex-Container mit Text-Overflow. Fehlt `min-width: 0` auf Flex-Items?
2. **Media vs Container Queries**: Nutze ich Media Queries für Komponenten-Layout? Wo wären Container Queries besser?
3. **gap vs margin**: Verwende ich noch `margin` in Flexbox/Grid statt `gap`?
4. **Layout Shift (CLS)**: Haben Bilder `width` und `height` Attribute? Fehlt `aspect-ratio`?
5. **Font Loading**: Nutze ich `font-display: swap`? Gibt es `size-adjust` für Fallback-Fonts?
6. **Nested Grids**: Wo könnte ich `subgrid` statt verschachtelter Grids nutzen?
7. **Dynamic Content**: Habe ich Skeleton Screens oder Platzhalter für lazy-loaded Content?
8. **Mobile Responsiveness**: Gibt es horizontales Scrolling auf Mobile (< 375px)?
Zeige mir konkrete CLS-Probleme und Quick Fixes mit Code-Beispielen.
Links: