Zum Hauptinhalt springen
CSS-Optimierung Teil 3: Layout & Responsiveness
#CSS #Layout #Grid #Flexbox #Responsive

CSS-Optimierung Teil 3: Layout & Responsiveness


Layout das performant UND stabil ist - Flexbox, Grid, Container Queries & CLS

6 Minuten Lesezeit

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-fit für Cards (dehnen OK)
  • auto-fill fü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 Width
  • cqh - Container Query Height
  • cqi - Container Query Inline
  • cqb - 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: