Site immer responsive
Eine Seite ist erst fertig, wenn sie python3 scripts/check_responsive.py besteht (kein horizontales Scrollen, nichts ragt über den Bildschirmrand, Touch-Ziele groß genug) bei allen 6 Referenzgrößen. Diese Prüfung läuft auch in der CI: Ein PR, der das responsive Design kaputt macht, kann nicht deployed werden.
Referenzbreiten (alle testen)
| Breite | Fall |
|---|---|
| 320 px | kleines Android, iPhone SE im Zoom |
| 375 px | iPhone Standard (Ziel Nr. 1: die Zielgruppe kommt von TikTok) |
| 414 px | großes Telefon |
| 768 px | Tablet im Hochformat |
| 1024 px | Tablet im Querformat / kleiner Laptop |
| 1440 px | Desktop |
Vom Skript getestete Größen: 320×640, 375×667, 414×896, 768×1024, 1024×600 (niedriger Bildschirm), 1440×900.
CSS-Regeln
- Mobile-First: Basis-Styles für 320 px, dann
@media (min-width: …)für größere Bildschirme. Breakpoints:600px,900px,1200px(keine anderen magischen Werte; eine Komponente kann@containerverwenden). - Keine feste Breite größer als 280 px ohne
min()/max-width: 100%:width: min(520px, 100%). - Flüssige Typografie mit
clamp(): Überschriftenclamp(32px, 7vw, 72px), Fließtext mindestens 16 px (niemals darunter auf mobilen Geräten, sonst zoomt iOS in Felder hinein). - Höhen:
min-height: 100svh(nicht100vh, das unter der mobilen Adressleiste verschwindet). Niemals eine festeheightbei einem Textblock. - Seitenabstände: Rand von 16 px auf mobilen Geräten (
space-4), plusenv(safe-area-inset-left/right)für Bildschirme mit Notch (der Viewport hat bereitsviewport-fit=cover). - Langer Text:
overflow-wrap: anywherefür URLs, Befehle und Dateinamen; Codeblöcke mitoverflow-x: autoinnerhalb des Blocks, niemals auf der Seite. - Grids:
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr))für Tutorial-Karten. - Dekorative Elemente, die überlaufen (z.B.
byte/spark-Blöcke, Canvas):position: fixedoder Eltern-Element mitoverflow: clip, und Größen mitmin(vw, px). - Touch: isolierte Schaltflächen und Links ≥ 44 × 44 px (24 px = Mindestgrenze des Skripts, WCAG 2.2), mindestens 8 px Abstand zwischen zwei Zielen. Keine Informationen, die nur bei Hover (
:hover) verfügbar sind::focus-visibleund Touch-Zustand vorsehen. - Videos und iFrames (YouTube):
aspect-ratio: 16 / 9; width: 100%; height: auto;— TikTok-Videos in9 / 16mitmax-width: 360px.
Bilder
- Immer
widthundheightim HTML (vermeidet Layout-Verschiebungen, CLS) +max-width: 100%; height: autoin CSS. - Formate: SVG für Logos und Symbole, WebP/AVIF für Screenshots, mit
srcset+sizes(z.B. 480w, 960w, 1600w). loading="lazy"unddecoding="async"unter dem Falz; niemals beim Hauptbild (LCP), dasfetchpriority="high"erhält.- Tutorial-Vorschaubilder:
aspect-ratio: 16 / 9; object-fit: cover.
Viewport (bereits vorhanden, nicht entfernen)
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
Verboten: maximum-scale=1, user-scalable=no (blockiert Zoom, schlecht für Barrierefreiheit).
Animation und mobile Performance
prefers-reduced-motionbeachten (Projektregel).- Canvas:
devicePixelRatioauf 2 begrenzen und Dichte unter 600 px reduzieren (bereits inapp.jsumgesetzt, dieses Prinzip beibehalten). - Kein schweres
backdrop-filterauf mobilen Geräten stapeln.
Überprüfen
# mit dem check-site-Container, der auf :8088 läuft, oder ohne Argument (lokaler Server auf site/)
python3 scripts/check_responsive.py # alle Seiten in site/
python3 scripts/check_responsive.py --shots /tmp/rs # + PNG-Screenshots pro Breite
Das Skript schlägt fehl, wenn scrollWidth > Breite, wenn ein sichtbares Element über den Rand ragt, wenn ein Touch-Ziel kleiner als 24 px ist (Links in einem Satz sind ausgenommen) oder wenn der Fließtext kleiner als 16 px ist. Screenshots bei 320 und 375 px ansehen, bevor du pushst.