# Frontend — Risques & vigilance : Responsive / adaptation mobile > Extrait de la base de connaissance Lead_tech. Voir `knowledge/frontend/risques/README.md` pour l'index complet. --- ## Gating responsive par largeur seule → fuite sur tablettes tactiles ### Risques - Le réflexe `@media (min-width: 768px|900px|1024px)` traite la largeur comme un proxy de l'UX cible ; ça casse sur **tablettes tactiles** (iPad Air 1180px, iPad Pro 1366px, Surface, Galaxy Tab) qui ont la largeur d'un desktop mais l'UX d'un doigt - Conséquences observées : swipe gestures désactivés sur iPad (alors que le swipe est l'UX tactile naturelle), scrollbars custom visibles en permanence, hover states bloquants au tap (1er tap = hover, 2e = click), pagination trop dense pour le doigt ### Symptômes - Une règle "desktop" gated par `min-width` seul se comporte mal sur iPad : interactions désactivées ou inadaptées, scrollbars inutiles ### Bonnes pratiques / mitigations **Gater par capacité d'input dès que la règle concerne une interaction** (hover, swipe, scrollbar visible, densité tactile, drag-and-drop, focus-ring discret). ```css @media (pointer: fine) { /* souris/trackpad précis : desktop, laptop */ } @media (pointer: coarse) { /* doigt/stylet imprécis : mobile, tablette tactile */ } @media (hover: hover) { /* hover stable */ } @media (hover: none) { /* hover simulé (tap) */ } /* "Vraie expérience desktop" : largeur ≥ X ET souris */ @media (pointer: fine) and (min-width: 900px) { /* scrollbars custom, hover, pagination dense */ } /* "Expérience tactile" : doigt, peu importe la largeur */ @media (pointer: coarse) { /* swipe, touch targets ≥44px, pas de hover stylé */ } ``` ```ts // équivalent runtime const isFinePointer = window.matchMedia('(pointer: fine)').matches; const isCoarseLarge = window.matchMedia('(pointer: coarse) and (min-width: 900px)').matches; ``` - **Garder `min-width` seul** pour le **layout pur** (grille, max-width container) : la largeur détermine la place, pas l'input. - Critère de décision : « Si je donne à un user iPad cette règle, préfère-t-il le comportement mobile ou desktop ? » Réponse "mobile" (swipe, touch dense) → `pointer: coarse` ; réponse "desktop" (layout 2 colonnes, max-width) → `min-width` seul. Doute → `pointer: fine` + `min-width`. - Support : `pointer:` / `hover:` (Interaction Media Features L4) universel depuis 2018, aucun fallback en 2026. Pattern CSS pur, applicable à toute stack. - Contexte technique : Vue 3 / Vite — RL799_V2 (chantier `feat/desktop-experience`, swipe rows / scrollbar globale / pagination Audit), 12-05-2026 --- ## Régressions mobile invisibles lors d'un chantier desktop responsive ### Risques - Un chantier "ajout desktop" sur une app mobile-first crée des régressions mobile par **effets de bord indirects**. Les devs travaillent en majorité sur viewport desktop → les régressions mobile n'apparaissent qu'au test final sur device, tardivement - 4 vecteurs récurrents : wrappers retirés qui fournissaient un gap implicite, classes globales qui cumulent leurs paddings, `display: contents`/grid qui change l'ordre DOM mobile, règles `min-width` qui fuient sur tablette tactile ### Symptômes - "Les espaces ont été mangés" (éléments mobiles collés), "le contenu est plus étroit qu'avant" (marges doublées), "l'ordre des cartes a changé" sans changement mobile intentionnel ### Bonnes pratiques / mitigations Les 4 vecteurs et leur fix : 1. **Wrapper retiré → gap implicite perdu** : un ``/`` retiré côté desktop portait un `gap`/`padding-top` qui structurait le rythme mobile. Fix : remettre explicitement `gap: var(--space-X)` sur le nouveau wrapper mobile, mesurer en pixels avant/après. 2. **Classes globales qui cumulent les paddings** : `.tenue-detail-container { padding-inline: 16px }` + `.page--dashboard { padding-inline: 16px }` = 32px sur mobile. Fix : neutraliser côté mobile (`.page--dashboard .tenue-detail-container { padding-inline: 0; }`). 3. **`display: contents` qui change l'ordre DOM mobile** : sur mobile le wrapper transparent fait suivre l'ordre HTML (réordonné pour le desktop), pas l'ordre historique mobile. Fix : préserver l'ordre via `flex` + `order` en `@media (max-width: 899px)`. 4. **Règles `@media (min-width)` qui fuient sur tablette tactile** : cf. `#risque-gating-responsive-largeur-vs-input`. Fix : ajouter `and (pointer: fine)` aux règles concernant une interaction. **Checklist QA mobile post-chantier desktop** (avant merge) : 1. Audit gap/padding mobile (diff visuel page par page vs version précédente) 2. Audit ordre DOM mobile pour chaque page touchée (surtout `display: contents`/grid) 3. Grep `@media (min-width:` dans le diff ; pour chaque règle concernant une interaction, ajouter `and (pointer: fine)` 4. Audit cumul de paddings : pour chaque nouvelle classe wrapper, vérifier qu'aucune classe interne globale n'ajoute son propre `padding-inline` 5. Test sur appareil **physique** réel (iPhone + Android + iPad tactile), pas seulement les émulateurs DevTools (qui simulent la largeur mais pas la nature du pointer) - Contexte technique : Vue 3.5 / Vite 7 — RL799_V2 (chantier `feat/desktop-experience`, passe QA mobile ~2h sur 7 fichiers), 12-05-2026