Site toujours responsive
Une page n'est terminée que si elle passe python3 scripts/check_responsive.py (aucun défilement horizontal, rien ne déborde de l'écran, cibles tactiles assez grandes) aux 6 tailles de référence. Ce contrôle tourne aussi dans la CI : une PR qui casse le responsive ne peut pas être déployée.
Largeurs de référence (à tester toutes)
| Largeur | Cas |
|---|---|
| 320 px | petit Android, iPhone SE en zoom |
| 375 px | iPhone standard (cible n° 1 : l'audience vient de TikTok) |
| 414 px | grand téléphone |
| 768 px | tablette portrait |
| 1024 px | tablette paysage / petit portable |
| 1440 px | bureau |
Tailles testées par le script : 320×640, 375×667, 414×896, 768×1024, 1024×600 (écran bas), 1440×900.
Règles CSS
- Mobile d'abord : styles de base pour 320 px, puis
@media (min-width: …)pour élargir. Points de rupture :600px,900px,1200px(pas de valeurs magiques ailleurs ; un composant peut utiliser@container). - Pas de largeur fixe supérieure à 280 px sans
min()/max-width: 100%:width: min(520px, 100%). - Typo fluide avec
clamp(): titresclamp(32px, 7vw, 72px), texte courant 16 px minimum (jamais en dessous sur mobile, sinon iOS zoome dans les champs). - Hauteurs :
min-height: 100svh(pas100vh, qui passe sous la barre d'adresse mobile). Jamais deheightfixe sur un bloc de texte. - Marges latérales : gouttière de 16 px sur mobile (
space-4), +env(safe-area-inset-left/right)pour les écrans à encoche (le viewport a déjàviewport-fit=cover). - Texte long :
overflow-wrap: anywheresur les URL, commandes et noms de fichiers ; blocs de code enoverflow-x: autodans le bloc, jamais sur la page. - Grilles :
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr))pour les cartes de tutos. - Éléments décoratifs qui débordent (blocs
byte/spark, canvas) :position: fixedou parent enoverflow: clip, et tailles enmin(vw, px). - Tactile : boutons et liens isolés ≥ 44 × 44 px (24 px = minimum bloquant du script, WCAG 2.2), 8 px d'écart minimum entre deux cibles. Pas d'information disponible uniquement au survol (
:hover) : prévoir:focus-visibleet l'état tactile. - Vidéos et iframes (YouTube) :
aspect-ratio: 16 / 9; width: 100%; height: auto;— vidéos TikTok en9 / 16avecmax-width: 360px.
Images
- Toujours
widthetheightdans le HTML (évite le décalage de mise en page, CLS) +max-width: 100%; height: autoen CSS. - Formats : SVG pour logos et icônes, WebP/AVIF pour les captures, avec
srcset+sizes(ex. 480w, 960w, 1600w). loading="lazy"etdecoding="async"sous la ligne de flottaison ; jamais sur l'image principale (LCP), qui prendfetchpriority="high".- Miniatures de tutos :
aspect-ratio: 16 / 9; object-fit: cover.
Viewport (déjà en place, ne pas retirer)
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
Interdit : maximum-scale=1, user-scalable=no (bloque le zoom, mauvais pour l'accessibilité).
Animation et performance mobile
prefers-reduced-motionrespecté (règle du projet).- Canvas : limiter
devicePixelRatioà 2 et réduire la densité sous 600 px (déjà fait dansapp.js, garder ce principe). - Pas de
backdrop-filterlourd empilé sur mobile.
Vérifier
# avec le conteneur de check-site lancé sur :8088, ou sans argument (serveur local sur site/)
python3 scripts/check_responsive.py # toutes les pages de site/
python3 scripts/check_responsive.py --shots /tmp/rs # + captures PNG par largeur
Le script échoue si scrollWidth > largeur, si un élément visible dépasse du bord, si une cible tactile fait moins de 24 px (les liens dans une phrase sont exemptés) ou si le texte courant fait moins de 16 px. Regarder les captures à 320 et 375 px avant de pousser.