Im März stellte Timo Wessels ein Thema vor, das ihn seit Langem begleitet: responsives Design, das wirklich „mitwächst“. Denn responsive bedeutet eben mehr als „es schrumpft auf dem Handy“. Es geht darum, dass sich alles stufenlos anpasst – Schriftgrößen, Abstände, Layouts –, und zwar ohne harte Sprünge und kaputte Stellen dazwischen.
Timo zeigte ein kleines, responsives Mini-Framework: kein Framework im klassischen Sinne, kein Build-Tool, keine Abhängigkeiten – nur modernes CSS. Und das Beste: Die meisten Techniken kommen ganz ohne Media Query aus. Die Grundlage von allem ist dabei ein durchdachtes Design-Token-System, also ein Satz zentral definierter CSS-Variablen, mit dem sich anschließend beliebig viele Seiten konsistent bauen lassen.
Warum ein Variablen-System der eigentliche Kern ist
Bevor es um die schicken neuen CSS-Features ging, machte Timo deutlich, dass das Wichtigste eine solide Basis ist: ein Variablen- bzw. Token-System. Die Idee dahinter ist denkbar einfach – man definiert einen Wert genau einmal an zentraler Stelle und verwendet ihn dann überall im Projekt:
:root {
--primary: #2d6a4f;
--space-m: 1.5rem;
}
.button {
background: var(--primary);
padding: var(--space-m);
}
Ändert sich später die Markenfarbe oder der Standard-Abstand, passt man genau eine Zeile an – und die gesamte Website zieht automatisch nach. Das klingt nach einer Kleinigkeit, ist in der Praxis aber der Unterschied zwischen einer Seite, die man pflegen kann, und einer, die mit jeder Änderung ein Stück mehr auseinanderfällt.
Der eigentliche Gewinn zeigt sich, wenn man Tokens aufeinander aufbaut. Man definiert die Grundwerte einmal – Farben, Abstände, Radien, Schatten – und leitet daraus zusammengesetzte Tokens ab. Aus echten Projekten von Timo (auf Basis von Automatic.css in Etch) sieht das zum Beispiel so aus:
:root {
/* Zusammengesetzte Tokens, die auf Grundwerten aufbauen */
--btn-gradient: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 55%, var(--primary-light) 100%);
--card-shadow: 0 0 0 1px rgba(45,51,33,0.08), 0 2px 8px rgba(45,51,33,0.06), 0 4px 20px rgba(45,51,33,0.04);
--spread-border-primary: 0 0 0 2px var(--primary);
}
Im Stylesheet schreibt man dann nur noch background: var(--btn-gradient) oder box-shadow: var(--card-shadow), statt jedes Mal lange, fehleranfällige Werte zu wiederholen. Will man später das Design-Gefühl der ganzen Seite verändern, geht das an einer einzigen Stelle. Genau das macht ein gutes Token-System so wertvoll: Es ist nicht nur Aufräumen, sondern die Voraussetzung dafür, dass die eigentlich spannenden, „mitwachsenden“ Techniken überhaupt sauber funktionieren.
Die Seitenstruktur: Section, Container, Gutter
Jede Website hat dasselbe Grundgerüst. Eine Section geht von Rand zu Rand – die volle Breite. Darin sitzt ein Container, der den Inhalt auf eine lesbare Breite begrenzt und zentriert. Erstaunlicherweise reichen für das gesamte Seitenlayout drei Variablen aus:
--content-width– wie breit darf der Inhalt maximal sein?--gutter– wie viel Seitenrand links und rechts?--section-padding– wie viel Abstand zwischen den Sektionen?
Der Gutter ist dabei schon fluid: Er wird auf großen Bildschirmen größer und auf kleinen kleiner.
Fluide Abstände mit clamp()
Das Herzstück des Abends. Normalerweise schreibt man Abstände in festen Pixeln oder behilft sich mit Media Queries – was aber zu einem harten Sprung beim jeweiligen Breakpoint führt. Die elegante Lösung heißt clamp():
padding: clamp(1rem, 0.86rem + 0.71vw, 1.5rem);
Hier gibt es ein Minimum (auf dem Handy), eine Formel, die mit der Fensterbreite wächst, und ein Maximum (auf dem Desktop). Der Browser wählt automatisch den passenden Wert dazwischen – stufenlos, ohne Sprung. Diese Formeln muss man übrigens nicht von Hand berechnen: utopia.fyi ist der bekannteste Rechner dafür.
In der Praxis genügt eine Skala von XS bis XXL – sechs Variablen, die alle Abstände auf der gesamten Seite abdecken und automatisch mitskalieren. Auch das ist wieder Tokenarbeit: einmal sauber angelegt, danach überall nutzbar.
Fluide Typografie
Exakt dasselbe Prinzip funktioniert für Schriftgrößen. Eine H1 ist auf dem Handy etwa 40 px groß, auf dem Desktop 76 px – und dazwischen skaliert sie stufenlos mit, ganz ohne Breakpoint. utopia.fyi hat dafür neben dem Spacing- auch einen Type-Calculator.
Grundstile und :where()
Für die Grundstile aller HTML-Elemente – Überschriften, Absätze, Links – setzte Timo auf :where(). Der Trick: :where() hat keine Spezifität. Jede Klasse, die man später schreibt, überschreibt diese Grundstile automatisch – kein Spezifitäts-Kampf, kein !important.
Das Karten-Grid: responsive ganz ohne Media Query
Der „Wow-Moment“ des Abends: ein Kartenraster, das sich von drei Spalten über zwei bis auf eine Spalte von selbst umstellt – und im CSS steht dafür keine einzige Media Query. Eine Zeile genügt:
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
Kurz erklärt: repeat(auto-fit, …) erzeugt so viele Spalten, wie hineinpassen; minmax(300px, 1fr) sorgt für mindestens 300 px pro Spalte bei gleichmäßiger Verteilung; und min(100%, 300px) fängt ganz kleine Bildschirme ab. Der Browser rechnet die Spaltenanzahl komplett selbst aus. Das ist die Stärke von CSS Grid: Es kann responsive sein, ohne dass man ihm sagen muss, wann.
Media Queries: wann man sie doch braucht
Wenn clamp() Schriften und Abstände und auto-fit die Grids responsive macht – wozu dann überhaupt noch Media Queries? Timos Antwort: nur dann, wenn sich das Layout grundlegend ändern muss, etwa wenn etwas auf dem Handy untereinander und auf dem Desktop nebeneinander stehen soll.
Wichtig dabei: Die Media Query gehört verschachtelt direkt an das Element – nicht irgendwo ans Ende der Datei. So sieht man sofort, was sich wo ändert. Und man arbeitet mit min-width statt max-width, also Mobile First: Das Handy-Layout ist der Standard, Desktop kommt als Ergänzung dazu.
Container Queries: das nächste Level für responsive Komponenten
Den Abschluss bildete das aus Timos Sicht spannendste Werkzeug von allen: Container Queries. Sie sind seit 2023 in allen großen Browsern verfügbar – aber erstaunlich viele kennen sie noch gar nicht oder trauen sich nicht heran. Dabei lösen sie ein Problem, das Media Queries grundsätzlich nicht lösen können.
Der Knackpunkt: Eine Media Query reagiert immer nur auf die Fensterbreite. Eine Karte weiß aber gar nicht, ob sie gerade in einem dreispaltigen Grid, in einer schmalen Sidebar oder in einem breiten Modal steckt – sie kennt nur die Größe des Viewports, nicht ihren eigenen verfügbaren Platz. Das führt dazu, dass dieselbe Komponente an verschiedenen Stellen oft falsch aussieht.
Container Queries drehen das um: Die Komponente reagiert auf die Breite ihres Elternelements statt auf die des Fensters. Man markiert das Elternelement als Container und lässt das Kind dann darauf reagieren:
/* Schritt 1: Elternelement als Container markieren */
.feature-karte {
container-type: inline-size;
}
/* Schritt 2: auf die Breite des Containers reagieren */
.feature-karte__inner {
flex-direction: column; /* schmal: gestapelt */
@container (min-width: 500px) {
flex-direction: row; /* breit genug: nebeneinander */
}
}
Das Ergebnis ist beeindruckend: Eine breite Karte zeigt Bild und Text nebeneinander, eine schmale Karte im selben Layout stapelt beides – und beide entscheiden das selbstständig, je nach dem Platz, den sie tatsächlich bekommen. Verschiebt man die Karte in eine engere Spalte, wechselt sie von alleine in die gestapelte Ansicht, ohne dass man irgendeine Fensterbreite festlegen müsste. Das ist die eigentliche Zukunft responsiver Komponenten: Jede Komponente kümmert sich um sich selbst und ist dadurch überall wiederverwendbar.
Praxis-Tipp: der „Has Me“-Selektor von Kevin Geary
Einen Stolperstein muss man bei Container Queries allerdings kennen: Das direkte Elternelement muss man von Hand als Container deklarieren – vergisst man das, funktioniert die ganze Sache stillschweigend nicht. Eine sehr elegante Lösung dafür ist der „Has Me“-Selektor von Kevin Geary, bei dem sich ein Block selbst sein Elternelement zum Container erklärt:
.card {
:has(> &) {
container-type: inline-size;
}
}
Damit hält sich die Container-Deklaration praktisch von selbst aktuell, egal wohin man die Komponente setzt – die CSS-Regel „reist“ mit dem Block mit. Wer tiefer einsteigen möchte, dem seien zwei Ressourcen von Kevin Geary ans Herz gelegt, die Timos Ansatz für diesen Vortrag stark geprägt haben:
Zusammenfassung
Was hat der Abend gezeigt? Zuerst und vor allem: ein durchdachtes Variablen- bzw. Design-Token-System als Fundament. Darauf aufbauend eine saubere Seitenstruktur aus Section, Container und Gutter mit nur drei Variablen. clamp() für Abstände und Schriftgrößen, die automatisch zwischen Handy und Desktop skalieren. auto-fit mit minmax() für Grids, die sich selbst anordnen. Media Queries nur noch für echte Layout-Wechsel, Mobile First mit min-width. Und schließlich Container Queries für Komponenten, die auf ihren eigenen Platz reagieren statt auf die Fensterbreite.
Das alles ist pures CSS – kein Framework, kein JavaScript, kein Build-Tool – und funktioniert heute in allen modernen Browsern. Der Kern der Botschaft: Wer einmal in ein gutes Token-System investiert, kann anschließend effizient, konsistent und mit erstaunlich wenig Code ganze Websites bauen, die auf jeder Bildschirmgröße gut aussehen.
Ressourcen zum Nachlesen
- utopia.fyi – Clamp-Calculator für Spacing und Typografie
- every-layout.dev – Layout-Patterns mit modernem CSS
- web.dev/learn/css – Googles kostenloser CSS-Kurs
- caniuse.com – Browser-Support checken
