Les landing statiques continuent d’expédier min-height: 100vh sur des heroes plein bord—et Safari sur iOS ment encore sur ce qu’est « un viewport » quand la barre d’URL se replie. Les designers voient des titres rognés de 40 à 120 px, des démos vidéo cachées derrière l’indicateur d’accueil et des CTA primaires qui n’apparaissent qu’après un scroll accidentel. En 2026, le CSS ajoute des unités viewport dynamiques—dvh, svh et lvh—qui suivent le chrome du navigateur actuellement visible plutôt que le plus grand viewport possible. Ce guide s’adresse aux équipes MPA qui veulent une voie WebKit reproductible, pas seulement l’émulation Chromium. Croisez avec scroll-padding pour en-têtes fixes et ancres, overscroll sur modales et images responsives et LCP afin d’aligner défilement, mise en page et politiques média.
Vous repartirez avec une matrice de choix d’unités, une pile progressive @supports et des garde-fous chiffrés (100dvh par défaut pour les heroes marketing, inset bas typique de 34 px sur iPhone entaillé, 45 minutes de QA matérielle par locale) que la revue design peut signer dans Git.
Pourquoi ce sujet refait surface en 2026 : les campagnes statiques se déploient en parallèle sur des dizaines de marchés, et chaque localisation modifie les retours à la ligne et la métrique. Un hero acceptable en anglais peut basculer sous le pli en français ou en finnois sans que le bug viewport change—il devient simplement visible. En parallèle, les hacks JavaScript qui réécrivent window.innerHeight à chaque frame de la barre perdent en acceptation : ils risquent le CLS, coûtent la batterie et compliquent les tests d’accessibilité.
Les MPA profitent particulièrement de ce rappel parce que le CSS critique est souvent une feuille artisanale sans reconciler de framework : une mauvaise unité reste des semaines dans le cache CDN. Si vous utilisez des design tokens ou des utilitaires, documentez quels composants peuvent adopter dvh et lesquels restent volontairement en vh, pour éviter un mélange hasardeux d’écouteurs resize et de CSS.
Pourquoi 100vh casse encore sur Safari mobile
Le vh classique se définit par rapport au large viewport—la zone disponible lorsque le chrome du navigateur est masqué. Safari mobile anime la barre d’URL supérieure et la barre d’outils inférieure pendant le défilement, si bien que la région peinte peut être bien plus petite que l’unité utilisée pour dimensionner. Chrome desktop en mode responsive ne reproduit pas la même courbe d’animation ; les équipes qui ne testent qu’en émulation livrent des régressions visibles uniquement sur les iPhones des dirigeants.
L’échec n’est pas « Safari a tort » : vh répondait à une question de layout-viewport en 2012 alors que le design produit 2026 attend de « dimensionner à ce que l’utilisateur voit maintenant ». Les unités dynamiques comblent cet écart sans écouteurs JavaScript qui luttent contre le défilement compositeur et épuisent la batterie sur de longues pages marketing.
L’API visualViewport et les niveaux de zoom iOS modulent aussi subtilement la hauteur perçue par rapport à Android Chrome. Même sans bloquer le zoom par pincement, les utilisateurs avec une taille de police système plus grande réduisent la zone utile. D’où l’intérêt de min-height plutôt que height rigide : le flux absorbe cette dérive tant que le conteneur n’est pas verrouillé sur une fausse hauteur fantôme.
Les zones juridiquement sensibles—bandeaux cookies, mentions médicales, disclaimers financiers—ne doivent pas être masquées par une barre d’outils qui ne rétrécit qu’après interaction. svh aide car il se comporte de façon conservatrice vers la configuration de chrome la plus petite, créant plutôt du vide qu’il ne cache du texte obligatoire.
dvh vs svh vs lvh—matrice de décision
dvh (dynamic viewport height) suit la hauteur visible actuelle pendant que les barres apparaissent et disparaissent. svh (small viewport height) s’ancre sur la configuration de chrome la plus petite—utile quand un CTA ne doit jamais passer sous la barre d’URL. lvh (large viewport height) correspond à l’ancien comportement de vh. Les contreparties horizontales dvw, svw et lvw comptent pour les carrousels qui débordent jusqu’aux encoches.
| Unité | Idéal pour | Risque si mal employée |
|---|---|---|
100dvh | Heroes plein écran, splash screens | De légers changements de hauteur au scroll peuvent déplacer une vidéo de fond |
100svh | Garanties au-dessus du pli, barres promo | Espace blanc supplémentaire quand le chrome disparaît |
100lvh | Parité legacy, bandeaux desktop uniquement | Mêmes bugs de rognage que le vh classique sur iOS |
calc(100dvh - 4rem) | Hero moins navigation fixe | Oublier env(safe-area-inset-*) sur appareils entaillés |
Par défaut, fixez les heroes marketing sur min-height: 100dvh sauf si la direction artistique impose un petit viewport verrouillé—par exemple des bannières légales visibles pendant que la barre d’URL est déployée.
Les unités horizontales sont souvent négligées : un hero vidéo 16:9 avec 100dvw et object-fit: cover peut rogner davantage près des encoches que prévu au Figma. Documentez des zones sûres de recadrage et reflétez-les dans des variables CSS pour que les développeurs n’improvisent pas.
Motifs hero pour HTML statique
Privilégiez min-height à une height rigide pour laisser les titres traduits grandir sans couper les descendantes. Centrez avec flexbox mais gardez le débordement scrollable sur le document, pas dans le hero, sauf si vous avez testé le scroll imbriqué avec overscroll-behavior. Quand une vidéo de fond se trouve derrière le texte, dimensionnez le conteneur en dvh et appliquez object-fit: cover sur le média pour que l’attribution LCP reste honnête.
Pour les layouts en deux colonnes (texte à gauche, mock appareil à droite), plafonnez le mock avec max-height: 70dvh afin que le paysage téléphone n’expulse pas les CTA hors écran. Associez une typo clamp() pour que le retour à la ligne tienne dans la boîte dynamique sans JavaScript.
Si vous générez des pages via Eleventy, Hugo ou équivalent, extrayez les règles critiques du hero dans un petit fichier identique par locale pendant que seules les chaînes changent. Ajoutez un contrôle Stylelint qui signale 100vh dans les sélecteurs de hero sans bloc @supports associé.
Accessibilité : si le hero autoplay une vidéo, les commandes doivent rester visibles même quand dvh bouge avec la barre d’outils. Le focus VoiceOver ne doit pas tomber dans un calque masqué ; testez avec « réduire les mouvements » car certaines animations influencent indirectement la hauteur perçue.
Safe areas et pieds collants
Les unités viewport dynamiques dimensionnent la boîte ; elles ne remplacent pas env(safe-area-inset-top) ni env(safe-area-inset-bottom). Les barres d’achat fixes devraient ressembler à ceci :
.sticky-cta {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding-bottom: max(1rem, env(safe-area-inset-bottom));
}
Sur iPhone 15, l’inset bas se situe souvent autour de 34 px ; ceux qui ne gardent que 16 px rognent encore les boutons. Ajoutez viewport-fit=cover dans la balise meta viewport lorsque vous dessinez volontairement derrière l’encoche—sans cela, les variables safe-area peuvent lire zéro alors que le matériel expose des marges.
Combiner une barre d’onglets fixe et un hero dvh peut produire des cibles tactiles trop étroites ; Apple recommande au moins 44×44 pt, indépendamment des unités dynamiques.
Amélioration progressive avec @supports
.hero {
min-height: 100vh;
}
@supports (height: 100svh) {
.hero { min-height: 100svh; }
}
@supports (height: 100dvh) {
.hero { min-height: 100dvh; }
}
Expédiez la cascade dans cet ordre pour que les WebKit plus anciens dégradent proprement. Si votre pipeline inliné le CSS critique, toute la pile doit tenir dans le premier budget 14 KB gzip—les heroes sont forcément above-the-fold.
Erreur fréquente : ne protéger que le sélecteur le plus interne pendant qu’un parent garde height: 100vh et invalide la pile enfant. Auditez la chaîne complète avec une règle de lint ou une bibliothèque de composants visuels.
Particularités WebKit en 2026
Safari macOS en fenêtre non plein écran mappe les unités dynamiques sur le rectangle de contenu visible, ce qui peut différer d’iOS de 8 à 12 px lorsque les onglets et barres d’outils sont visibles. Capturez des captures sur les deux plateformes. Quand 100dvh anime pendant les transitions de barre, désactivez les parallaxes coûteuses background-attachment: fixed—elles déclenchent des repeints sur le thread principal et font tomber la fluidité sous 55 ips sur puces M de base sous charge.
Les éléments positionnés en sticky dans un hero dvh peuvent « sauter » quand l’unité dynamique change. Déplacez la navigation sticky vers la racine du document et ne dimensionnez que le fond décoratif avec dvh.
Safari Technology Preview peut précéder Stable sur la sémantique viewport. Pour les assets marketing longue durée, planifiez une courte régression trimestrielle après les grosses mises à jour iOS.
Liste QA sur matériel réel
- Charger la page avec la barre d’URL déployée ; vérifier que le CTA principal est visible sans scroll.
- Défiler d’environ 120 px ; le repli de la barre ne doit pas masquer de texte légal obligatoire.
- Passer en paysage ; les promos
svhdoivent dégager l’indicateur d’accueil. - VoiceOver sur le pied collant ; le padding d’inset bas ne doit pas expulser le focus hors écran.
- Comparer des filmstrips entre Safari stable et STP lorsqu’Apple modifie le viewport.
- Archiver des PNG avant/après dans le ticket pour validation design.
Budgetez 45 minutes par locale lorsque les heroes contiennent des chaînes plus longues que l’anglais d’au moins 30 % ; l’allemand et le portugais brésilien révèlent des hypothèses de layout masquées par des textes courts.
Les diffs screenshot automatisés sur un Mac mini loué via SSH accélèrent les régressions, mais ne remplacent pas le geste pouce réel, car la physique de la barre d’outils diffère du scroll molette.
FAQ
Dois-je remplacer tout vh par dvh ?
Non—les bandeaux décoratifs au milieu de page peuvent conserver vh. Priorisez les heroes plein écran, les feuilles modales et les CTA collants qui touchent au chrome mobile.
Lighthouse pénalise-t-il dvh ?
Les outils lab peuvent encore signaler du layout shift si les médias du hero n’ont pas de dimensions ; les unités dynamiques ne remplacent pas les attributs width/height.
Puis-je mélanger innerHeight JavaScript et le CSS ?
Évitez deux sources de vérité—les écouteurs resize réintroduisent du saccadé. Préférez les unités dynamiques CSS avec repli @supports.
Louer un Mac mini Apple Silicon via MacHTML donne le même build WebKit que les parties prenantes sur le terrain—pas un conteneur Linux qui imite Safari. Les nœuds exposent SSH pour des pipelines de diff screenshot et VNC optionnelle pour analyser les animations image par image. La consommation au repos reste souvent entre 6 et 12 W, donc garder le matériel pour un audit viewport de deux semaines coûte moins cher qu’une régression hero en plein lancement.
Le tarif affiché tourne autour de 16,9 $ par jour, ce qui bat l’achat d’une autre machine de bureau qui dort après la campagne. Une fois la QA terminée, arrêtez l’instance ; vos piles dvh restent dans Git pendant que le métal n’est pas amorti sur 36 mois de cycles d’achat.
Réparer les viewports Safari mobile sur un vrai macOS
Louez un Mac mini cloud pour valider les heroes dvh, le padding safe-area et les CTA collants dans WebKit avant de fusionner le CSS statique.