ONMA Ratgeber

Website Responsive Design: planen, bauen, abnehmen

Von Breakpoints aus dem Inhalt über srcset und clamp() bis zum Prüfplan: der Weg durch ein responsives Website-Projekt bis zur Abnahme.

Smartphone auf dunklem Untergrund, auf dem Display eine Google-Trefferliste zur Suche „Online Marketing Experte“

Responsive Design ist in einem Website-Projekt keine Eigenschaft, die man am Ende einschaltet, sondern eine Kette von Entscheidungen: wo das Layout umbricht, welche Bildvariante ausgeliefert wird, wie groß Schrift und Schaltflächen auf einem schmalen Gerät werden und woran man am Ende festmacht, dass die Seite fertig ist. Dieser Leitfaden führt durch diese Kette in der Reihenfolge, in der sie im Projekt auftaucht, und endet mit einem Prüfplan, den man bei der Abnahme reproduzierbar abarbeiten kann.

Zur Einordnung: Der Begriff stammt aus Ethan Marcottes Artikel in A List Apart vom 25. Mai 2010, der fluide Raster, flexible Bilder und Media Queries als die drei Bestandteile des Ansatzes benennt. MDN beschreibt Responsive Webdesign heute als Webdesign-Ansatz, der sicherstellt, dass Webseiten auf allen Bildschirmgrößen und Auflösungen gut gerendert werden. Media Queries selbst sind ein W3C-Standard, “Media Queries Level 3” wurde am 19. Juni 2012 W3C Recommendation. Adaptive Design, das auf dem Server feste Layoutstufen ausliefert, grenzt sich davon ab, spielt in einem modernen Website-Projekt aber praktisch keine Rolle mehr. Mehr Definition braucht es hier nicht, ab jetzt geht es um die konkrete Umsetzung.

Warum die Reihenfolge zählt

Zwei Gründe sprechen dafür, die mobile Darstellung nicht als Nachlauf zu behandeln. Der erste ist technisch: Google indexiert Websites mobile-first. Für Indexierung und Ranking wird primär die mobile Version der Inhalte herangezogen. Was auf dem schmalen Viewport fehlt oder ausgeblendet ist, fehlt damit auch in der Bewertung. Der zweite ist rechtlich und praktisch: WCAG 2.1 Erfolgskriterium 1.4.10 (Reflow) verlangt, dass Inhalte bei einer Breite von 320 CSS-Pixeln ohne zweidimensionales Scrollen darstellbar sind. Ein Layout, das erst nachträglich schmal gemacht wird, reißt genau an dieser Stelle: feste Pixelbreiten, Tabellen, überbreite Bilder oder absolut positionierte Elemente führen zu Fehlern.

Praktisch heißt das: Das schmale Layout ist der Ausgangszustand, die breiteren sind die Ergänzungen. Wer mobile zuerst baut, schreibt Media Queries, die etwas hinzufügen, statt welche, die etwas reparieren.

Breakpoints aus dem Inhalt ableiten, nicht aus Gerätelisten

Die häufigste Fehlentscheidung am Projektanfang ist eine Liste von Gerätebreiten als Grundlage der Breakpoints. Diese Liste ist immer veraltet, sie wächst mit jedem Modell und sie beschreibt Hardware statt Layout. Der belastbare Weg ist umgekehrt: Man vergrößert den Browser stufenlos und notiert die Breite, ab der der Inhalt anfängt, schlecht auszusehen. Genau dort gehört ein Breakpoint hin.

Typische Auslöser, die man beim Ziehen des Fensters beobachtet:

  • Eine Textspalte wird so breit, dass Zeilen unangenehm lang werden. Als Orientierung dient die Zeilenlänge, nicht die Fensterbreite.
  • Eine Kartenliste hat so viel Platz, dass zwei oder drei Spalten sinnvoll werden.
  • Die Navigation passt in einer Zeile nebeneinander und braucht kein Menü hinter einer Schaltfläche mehr.
  • Ein Bild neben Text hätte genug Raum, um wirklich neben dem Text zu stehen statt darüber.

Daraus entstehen in einem normalen Projekt drei bis fünf Breakpoints, oft weniger als erwartet. Sie bekommen im CSS am besten sprechende Namen im Kommentar oder als Custom Property, damit im Review nachvollziehbar bleibt, welche Entscheidung dahintersteht.

Für die Einheit gilt: Breakpoints in em reagieren mit, wenn Nutzer die Schriftgröße im Browser hochsetzen, Breakpoints in px nicht. In einem Projekt mit Barrierefreiheitsanspruch ist em deshalb die ruhigere Wahl.

.karten { display: grid; gap: 1.5rem; }

/* ab hier passen zwei Karten nebeneinander, ohne dass die Überschrift umbricht */
@media (min-width: 40em) {
  .karten { grid-template-columns: repeat(2, 1fr); }
}

Viele Layoutwechsel brauchen überhaupt keine Media Query. grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)) verteilt Karten von allein, flex-wrap: wrap bricht Zeilen um, min() und max() begrenzen Breiten. Jede Media Query, die man dadurch einspart, ist eine Stelle weniger, die bei einer späteren Inhaltsänderung nachgezogen werden muss.

Das Viewport-Meta-Tag setzen und richtig setzen

Ohne das Meta-Viewport-Tag rendern mobile Browser die Seite in einem breiten virtuellen Viewport und skalieren sie herunter. Das Ergebnis ist eine unlesbar verkleinerte Desktop-Ansicht, in der sämtliche Media Queries wirkungslos bleiben, weil der Browser nicht die reale Gerätebreite meldet. Empfohlen ist:

<meta name="viewport" content="width=device-width, initial-scale=1">

Zwei Ergänzungen, die man in älteren Vorlagen findet, gehören ausdrücklich nicht hinein: user-scalable=no und ein maximum-scale, das unter 5 liegt. Beides verhindert oder begrenzt das Zoomen und nimmt genau den Nutzern eine Bedienhilfe weg, die sie am dringendsten brauchen. Wenn der Zoom im Projekt als Notlösung gegen ein kaputtes Layout gedacht war, ist nicht der Zoom das Problem.

Bei Geräten mit runden Ecken oder Kamera-Aussparung kommt viewport-fit=cover in Verbindung mit den env(safe-area-inset-*)-Variablen dazu, damit Inhalt nicht unter der Systemleiste verschwindet. Das ist eine Detailentscheidung, keine Grundeinstellung.

Media Queries fürs Seitenlayout, Container Queries für Komponenten

Diese Abgrenzung erspart in der Umsetzung mehr Arbeit als jede andere. Media Queries fragen den Viewport ab und sind damit das richtige Werkzeug für alles, was die Seite als Ganzes betrifft: Kopfbereich, Navigation, die Aufteilung in Haupt- und Nebenspalte sowie Seitenränder.

Sobald es um eine Komponente geht, ist der Viewport die falsche Bezugsgröße. Dieselbe Teaser-Karte steht einmal in einer breiten Hauptspalte und einmal in einer schmalen Seitenleiste, der Viewport ist in beiden Fällen identisch, der verfügbare Platz nicht. Container Queries (@container) erlauben es, eine Komponente an der Breite ihres Containers statt am Viewport auszurichten. Sie sind in Chrome ab Version 105, Safari ab 16 und Firefox ab 110 verfügbar.

.spalte { container-type: inline-size; }

.teaser { display: grid; gap: 1rem; }

@container (min-width: 28rem) {
  .teaser { grid-template-columns: 12rem 1fr; align-items: start; }
}

Die Faustregel für das Projekt: Wenn eine Komponente an mehr als einer Stelle vorkommt oder vorkommen könnte, bekommt sie eine Container Query. Was übrig bleibt, sind erstaunlich wenige echte Media Queries auf Seitenebene. Für Projekte mit Anspruch auf sehr alte Browser lässt sich das Layout ohne Container Query als einspaltige Variante belassen, die Komponente bleibt dann benutzbar, nur nicht optimal.

Bilder über srcset und picture ausliefern

Ein Bild, das auf dem Desktop 1600 Pixel breit gebraucht wird, ist auf einem Telefon Verschwendung an Datenvolumen und Renderzeit. Die HTML-Attribute srcset und sizes sowie das picture-Element sind der standardisierte Weg, dem Browser mehrere Bildvarianten anzubieten, sodass er die für Viewport und Gerätepixelverhältnis passende Datei lädt. Das Gerätepixelverhältnis kommt hier nur als Parameter vor, den der Browser selbst einsetzt, es ist nichts, was man im CSS abfragen sollte.

Zwei Fälle sind zu unterscheiden:

Gleiches Bild, verschiedene Größen. Dafür nutzt man srcset mit Breitenangaben plus sizes, das dem Browser sagt, wie breit das Bild im Layout tatsächlich sein wird. sizes muss zu den eigenen Breakpoints passen, sonst lädt der Browser rechnerisch korrekt die falsche Datei.

<img src="halle-800.jpg"
     srcset="halle-400.jpg 400w, halle-800.jpg 800w, halle-1600.jpg 1600w"
     sizes="(min-width: 60em) 40rem, 100vw"
     width="1600" height="900"
     alt="Blick in die fertig eingerichtete Ausstellungshalle"
     loading="lazy" decoding="async">

Anderer Bildausschnitt oder anderes Format. Dafür nutzt man picture mit mehreren source-Elementen, etwa ein Hochformat-Zuschnitt für schmale Viewports oder ein modernes Dateiformat mit JPEG als Rückfall. Hier entscheidet der Autor, nicht der Browser.

Unabhängig vom Fall gehören width und height an jedes Bild. Der Browser reserviert daraus das Seitenverhältnis, bevor die Datei da ist, und genau das verhindert das Nachrutschen des Textes, das später in der Abnahme als Layout Shift auffällt. loading="lazy" gehört an Bilder unterhalb des ersten Bildschirms, ausdrücklich nicht an das erste große Bild der Seite.

Typografie über clamp() skalieren

Schriftgrößen an jedem Breakpoint neu zu setzen, erzeugt viele kleine Regeln und sichtbare Sprünge. clamp() setzt einen Wert aus Minimum, bevorzugtem Wert und Maximum zusammen und wird damit für fluide Schriftgrößen ohne Media Query eingesetzt.

h1 { font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem); }
body { font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); }
.inhalt { max-width: 68ch; }

Der mittlere Term sollte immer einen rem-Anteil enthalten. Eine reine vw-Angabe skaliert nicht mehr mit, wenn Nutzer die Schriftgröße im Browser ändern, und kann den Zoom praktisch aushebeln. Minimum und Maximum gehören außerdem geprüft, nicht geraten: Das Minimum muss bei 320 CSS-Pixeln noch lesbar sein, das Maximum darf auf einem sehr breiten Monitor nicht plakativ wirken. Die Zeilenlänge begrenzt man besser über max-width in ch als über die Schriftgröße.

Dasselbe Muster trägt für Abstände. Ein clamp() auf dem Innenabstand des Seitenrahmens ersetzt oft drei Media Queries.

Der Prüfplan für die Abnahme

Ab hier geht es nicht mehr um Bauen, sondern um Nachweisen. Die folgenden sieben Prüfungen sind so formuliert, dass zwei Personen unabhängig voneinander zum selben Ergebnis kommen.

1. Emulation als Vorprüfung. Der Responsive Design Mode in Firefox und der Gerätemodus in den Chrome DevTools emulieren Viewport-Größen und Gerätepixelverhältnisse. Man zieht die Breite stufenlos von sehr breit bis sehr schmal und achtet auf Sprünge, überlappende Elemente und abgeschnittene Texte. Diese Werkzeuge ersetzen keinen Test auf echter Hardware, da Touch-Verhalten und Renderer abweichen. Die Emulation findet Layoutfehler, nicht Bedienfehler.

2. Reflow bei 320 CSS-Pixeln. Fenster oder Emulation auf 320 Pixel Breite stellen und die Seite von oben nach unten durchgehen. Kein Inhalt darf horizontales Scrollen erfordern, kein Text darf abgeschnitten sein, keine Funktion darf verschwinden. Das ist die Prüfung zu WCAG 2.1 Erfolgskriterium 1.4.10. Ausgenommen sind nur Inhalte, die zwingend zweidimensional sind, etwa große Datentabellen oder Karten, und diese bekommen dann einen eigenen scrollbaren Bereich statt die ganze Seite mitzureißen.

3. Kein horizontales Scrollen auf der Seitenebene. Der schnellste Nachweis ist ein Blick in die Konsole, der das schuldige Element benennt:

document.querySelectorAll('*').forEach(el => {
  if (el.getBoundingClientRect().right > document.documentElement.clientWidth + 1) {
    console.log(el);
  }
});

Typische Verursacher sind feste Breiten, negative Ränder, 100vw in einem Container mit Innenabstand und lange Wörter oder URLs ohne Umbruchregel.

4. Zoom auf 200 Prozent. Bei unverändertem Fenster die Browservergrößerung auf 200 Prozent stellen. Das Layout muss umbrechen wie bei einem schmalen Viewport, nicht überlaufen. Diese Prüfung findet zuverlässig alle Stellen, an denen Breakpoints in px statt in em gesetzt wurden.

5. Touch-Zielgrößen. WCAG 2.1 Erfolgskriterium 2.5.5 (Target Size, Level AAA) nennt 44 mal 44 CSS-Pixel als Mindestgröße für Zeiger-Ziele. Geprüft werden alle Schaltflächen, Menüpunkte, Icon-Links, Schließen-Kreuze und Formularelemente. Häufige Fundstellen sind Social-Icons im Fußbereich, Pfeile in Bildergalerien und Links, die eng untereinander in einer Liste stehen. Wenn das sichtbare Element kleiner bleiben soll, vergrößert man die Trefferfläche über Innenabstand oder ein Pseudoelement.

6. Layout Shift. Ein Cumulative Layout Shift von 0,1 oder weniger gilt laut web.dev als “gut”, gemessen wird beim 75. Perzentil der Seitenaufrufe. Für die Abnahme reicht die Messung im Labor plus eine visuelle Kontrolle: Seite mit gedrosselter Verbindung laden und beobachten, ob Text nach unten rutscht, sobald Bilder, eingebettete Inhalte oder eine Webschrift eintreffen. Die drei üblichen Ursachen sind fehlende width/height an Bildern, nachgeladene Banner ohne reservierten Platz und ein Schriftwechsel ohne passende Rückfallmetrik.

7. Echte Geräte. Mindestens ein aktuelles kleines Telefon, ein Tablet im Quer- und Hochformat und ein Gerät mit iOS, weil dessen Renderer und Formularelemente sich anders verhalten. Geprüft wird nicht das Aussehen, das hat Schritt 1 erledigt, sondern die Bedienung: Trifft man die Schaltflächen mit dem Daumen, überdeckt die eingeblendete Tastatur das aktive Feld, funktioniert ein aufklappendes Menü mit Fingerdruck statt mit Mauszeiger, bleibt eine fixierte Kopfzeile beim Scrollen erträglich.

Checkliste für die Abnahme

  • Viewport-Meta-Tag vorhanden, ohne user-scalable=no und ohne zu kleines maximum-scale.
  • Breakpoints sind aus dem Inhalt begründet und im Code kommentiert, keine Geräteliste.
  • Layout ohne horizontales Scrollen bei 320 CSS-Pixeln, Prüfung dokumentiert.
  • Zoom auf 200 Prozent bricht das Layout um, statt es überlaufen zu lassen.
  • Alle Bilder mit srcset/sizes oder picture, jeweils mit width und height.
  • sizes passt zu den tatsächlichen Layoutbreiten, geprüft an mindestens zwei Breakpoints.
  • Erstes Bild oberhalb der Falz ohne loading="lazy".
  • Fluide Schrift über clamp() mit rem-Anteil, Minimum bei 320 Pixeln lesbar.
  • Zeilenlänge im Fließtext begrenzt.
  • Wiederverwendete Komponenten reagieren über Container Queries, nicht über den Viewport.
  • Alle Zeiger-Ziele mindestens 44 mal 44 CSS-Pixel, inklusive Icons und Fußbereich.
  • Kein sichtbarer Layout Shift beim Laden mit gedrosselter Verbindung.
  • Test auf mindestens drei echten Geräten, davon eines mit iOS, Ergebnis notiert.
  • Formulare, Tabellen und eingebettete Inhalte einzeln auf schmalem Viewport geprüft.

Was nach der Abnahme kommt

Responsive Design bleibt nur so lange intakt, wie der Inhalt sich innerhalb der geprüften Annahmen bewegt. Eine später eingefügte Tabelle mit acht Spalten, eine Video-Einbettung mit fester Breite oder eine Überschrift mit einem sehr langen zusammengesetzten Wort kippen jede der obigen Prüfungen einzeln. Sinnvoll ist deshalb, die Checkliste nicht als Projektabschluss abzulegen, sondern als wiederkehrende Prüfung bei jeder größeren Inhaltsänderung. Der Aufwand dafür liegt bei wenigen Minuten, sobald die Prüfschritte einmal beschrieben sind, und ist deutlich kleiner als die Suche nach dem Element, das eine Seite drei Wochen nach dem Livegang wieder seitlich scrollen lässt.