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
100vhsur 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
100svhpour des mises en page stables en pleine hauteur qui s’adaptent à l’écran visible lorsque les barres d’outils sont affichées. - Réservez
100dvhaux 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
vhcomme é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)
Discover how at OpenReplay.com.
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ésente | Idéal pour |
|---|---|---|
lvh | Viewport large (barres d’outils rétractées) | Même comportement que vh actuel |
svh | Viewport petit (barres d’outils visibles) | Mises en page stables, contenu toujours visible |
dvh | Viewport 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..