Back

Quand 100vh ment : corriger les problèmes de viewport mobile

Quand 100vh ment : corriger les problèmes de viewport mobile

Vous créez une section hero en pleine hauteur. Elle est parfaite dans Chrome DevTools. Vous l’ouvrez sur votre téléphone et le contenu du bas est coupé — le bouton CTA que vous avez passé du temps à positionner se cache derrière la barre d’adresse du navigateur. Ça vous dit quelque chose ?

Ce n’est plus une bizarrerie propre à Safari. C’est une conséquence de la façon dont les unités de viewport sont fondamentalement définies, et cela affecte aussi Chrome, Firefox et Samsung Internet sur mobile.

Points clés à retenir

  • 100vh sur mobile est calculé par rapport au viewport large (barres d’outils rétractées), qui est plus grand que ce que les utilisateurs voient réellement au chargement initial.
  • Utilisez 100svh pour des mises en page stables en pleine hauteur qui s’adaptent à l’écran visible lorsque les barres d’outils sont affichées.
  • Réservez 100dvh aux cas où vous souhaitez explicitement que la mise en page se redimensionne lorsque l’interface du navigateur change, et acceptez le coût du reflow.
  • Combinez les unités de viewport avec env(safe-area-inset-bottom) sur les écrans edge-to-edge pour éviter que le contenu ne se retrouve derrière l’interface système.

Pourquoi 100vh ment sur mobile

La cause profonde se résume à deux concepts de viewport différents :

  • Viewport de mise en page (layout viewport) : ce que le navigateur utilise pour calculer les longueurs CSS, y compris vh
  • Viewport visuel (visual viewport) : ce que l’utilisateur voit réellement à l’écran

Les navigateurs mobiles maintiennent intentionnellement le viewport de mise en page fixe même lorsque la barre d’adresse et la barre d’outils de navigation se rétractent pendant le défilement. Cela signifie que 100vh est calculé par rapport à l’état avec barres d’outils déployées — le viewport large — et cette valeur est plus grande que l’écran visible au premier chargement de la page.

Ce n’est pas un bug. La spécification CSS définit vh comme équivalent à lvh (large viewport height). Le navigateur se comporte correctement. Votre mise en page n’en tient simplement pas compte.

C’est pourquoi l’émulation mobile de DevTools semble correcte : elle ne simule pas l’interface dynamique du navigateur. La barre d’adresse ne se rétracte jamais dans un simulateur.

L’impact en conditions réelles

  • Les sections hero débordent de 56 à 80 px au chargement initial
  • Les pieds de page fixes sont masqués par la barre de navigation
  • Les modales plein écran coupent le contenu en bas
  • Les mises en page sautent lorsque les barres d’outils se rétractent en cours de défilement (si vous utilisez dvh)

Solutions modernes : svh, dvh et lvh

CSS vous offre désormais trois unités de hauteur de viewport explicites qui correspondent à différents états des barres d’outils :

UnitéReprésenteIdéal pour
lvhViewport large (barres d’outils rétractées)Même comportement que vh actuel
svhViewport petit (barres d’outils visibles)Mises en page stables, contenu toujours visible
dvhViewport dynamique (état actuel)Mises en page adaptatives, mais provoque du reflow

Pour la plupart des sections pleine hauteur : utilisez svh

.hero {
  height: 100vh;     /* Fallback pour les anciens navigateurs */
  height: 100svh;    /* S'adapte à l'écran visible au chargement */
}

100svh dimensionne l’élément au viewport le plus petit possible — ce qui signifie qu’il s’adapte même lorsque les barres d’outils sont entièrement visibles. Pas de débordement, pas de coupure.

Quand vous voulez un ajustement dynamique : utilisez dvh avec précaution

.full-height {
  height: 100vh;     /* Fallback */
  height: 100dvh;    /* Se redimensionne lorsque les barres d'outils se rétractent */
}

Attention : dvh recalcule à mesure que l’interface du navigateur change pendant le défilement. Cela peut provoquer des décalages de mise en page visibles et des repeints. Ce n’est pas le choix par défaut approprié pour la plupart des sections hero ou modales — utilisez-le uniquement lorsque vous souhaitez explicitement que l’élément se redimensionne avec l’état des barres d’outils.

Support navigateur

svh, dvh et lvh sont supportés dans Chrome 108+, Safari 15.4+ et Firefox 101+. Combinés, cela couvre plus de 90 % des utilisateurs dans le monde. Pour les navigateurs plus anciens, le fallback 100vh gère le reste.

Cas particuliers à connaître

Safe area insets : Sur les écrans edge-to-edge (encoche iPhone/Dynamic Island), combinez les unités de viewport avec env(safe-area-inset-bottom) pour éviter que le contenu ne se retrouve derrière l’interface système :

.hero {
  height: 100svh;
  padding-bottom: env(safe-area-inset-bottom);
}

Clavier virtuel : Le clavier virtuel affecte principalement le viewport visuel, et son interaction avec le dimensionnement du viewport de mise en page peut varier selon les navigateurs et les WebViews. C’est distinct des unités de viewport liées aux barres d’outils et peut nécessiter une gestion JavaScript ou l’API VirtualKeyboard comme amélioration progressive.

WebViews et navigateurs embarqués : Les navigateurs intégrés aux applications (Instagram, LinkedIn) ont souvent un comportement de viewport non standard. Testez sur de vrais appareils, pas seulement sur les navigateurs système.

Conclusion

Arrêtez d’utiliser 100vh par défaut pour vos mises en page mobiles pleine hauteur. Utilisez 100svh pour les sections stables qui doivent s’adapter à l’écran visible au chargement. Réservez 100dvh aux cas où le redimensionnement dynamique est intentionnel. La nouvelle famille d’unités de viewport existe précisément parce que l’ancien comportement a toujours été un compromis — vous avez maintenant les outils pour être explicite sur ce que vous voulez réellement.

FAQ

Pas partout. 100svh vous donne la hauteur de viewport la plus petite, qui est plus courte que 100vh. Pour les éléments qui doivent remplir l'écran uniquement après la rétraction des barres d'outils, 100lvh ou 100dvh peuvent être plus appropriés. Utilisez 100svh spécifiquement pour le contenu qui doit être entièrement visible au chargement initial de la page avec les barres d'outils affichées.

Cela peut. Parce que dvh recalcule chaque fois que la barre d'outils du navigateur se rétracte ou se déploie pendant le défilement, cela déclenche des recalculs de mise en page et des repeints. Pour les sections hero statiques ou les modales, cette surcharge est inutile. Réservez dvh aux éléments où vous souhaitez intentionnellement que la hauteur suive le viewport visible actuel en temps réel.

Le comportement varie. Dans les iframes standard, les unités de viewport font référence au viewport propre de l'iframe, pas à la page parente. Dans les WebViews utilisées par les navigateurs intégrés aux applications comme Instagram ou Facebook, le comportement des barres d'outils est non standard et les calculs d'unités de viewport peuvent être imprévisibles. Testez toujours sur de vrais appareils dans les contextes embarqués spécifiques que vos utilisateurs rencontrent.

Les unités svh, dvh et lvh ne sont pas affectées par le clavier virtuel. Le clavier réduit le viewport visuel mais pas le viewport de mise en page que ces unités référencent. Pour gérer les décalages de mise en page liés au clavier, consultez l'API VirtualKeyboard, qui vous donne un contrôle programmatique sur la façon dont votre mise en page réagit aux changements de visibilité du clavier.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay