The Mobile Viewport Problem
Every web developer has encountered this frustrating behavior: you build a hero component that spans the full screen height on your desktop, but on mobile, the bottom portion gets hidden behind the browser chrome. The call-to-action button that should be perfectly visible instead sits outside the viewport, forcing users to scroll.
This isn't a bug in your code--it's a fundamental difference in how mobile browsers handle viewport units. This guide covers the complete solution, from legacy workarounds to modern CSS viewport units that finally solve this problem correctly.
What You'll Learn
- Why 100vh fails on mobile browsers
- Legacy workarounds and their limitations
- Modern CSS viewport units (dvh, svh, lvh)
- Code examples for full-height layouts
- Browser support and fallback strategies
For developers working on responsive web applications, understanding viewport units is essential for creating layouts that work seamlessly across all devices.
The Problem: Why 100vh Fails on Mobile
On desktop browsers, height: 100vh works exactly as expected--the element takes up 100% of the visible viewport height. However, mobile browsers operate differently.
Mobile browsers have dynamic browser chrome (address bars, tab bars, toolbars) that expand and collapse as users interact with the page. The critical issue is that 100vh represents the viewport height when these toolbars are in their collapsed state, which only occurs after the user begins scrolling.
UI Patterns Affected
This behavior impacts several common design patterns:
- Full-screen hero sections with bottom-aligned CTAs
- Fixed footers and navigation bars
- Landing pages designed to fill the entire viewport
- Modal dialogs and overlay components
- Single-page application layouts
Frontend.fyi's guide to viewport units explains how mobile browsers handle retractable UI elements and why 100vh represents the collapsed state.
Understanding this behavior is essential for creating mobile-first designs that rely on viewport-relative sizing. Related techniques like CSS sticky headers often need special handling to account for mobile viewport behavior.
Legacy Solutions: The -webkit-fill-available Workaround
Before modern viewport units were widely supported, developers used a vendor-prefixed property as a progressive enhancement. The solution involves using -webkit-fill-available, which tells WebKit browsers to use the "fill available" height rather than the viewport height.
CSS-Tricks' original article documented this approach as the primary solution for mobile WebKit browsers.
1/* Legacy -webkit-fill-available workaround */2body {3 min-height: 100vh;4 min-height: -webkit-fill-available;5}6 7html {8 height: -webkit-fill-available;9}Why Legacy Solutions Are Problematic
This approach has significant limitations:
- Vendor-prefixed: May not work consistently across browsers
- Behavior changes: Chrome updated behavior to match Firefox's implementation
- Not a fix: Only works around the issue rather than solving it
- Future compatibility: Browser behavior may continue to evolve
As noted in discussions on the CSS-Tricks solution, effects of rotating devices can cause unexpected behavior, and Chrome doesn't completely ignore the property, leading to inconsistent results.
For production applications, relying on legacy workarounds is not recommended.
The Modern Solution: Dynamic Viewport Units
CSS has introduced three new viewport units specifically designed to address the mobile browser chrome issue. Frontend.fyi's tutorial covers these new units in detail with practical examples.
Large Viewport (lvh)
Size with all retractable UI elements in their expanded state. Use 100lvh when you want the element to fill the entire screen including where the browser chrome would appear.
Small Viewport (svh)
Size with all retractable UI elements in their collapsed state. Use 100svh when you want the element to fit within the smallest visible area.
Dynamic Viewport (dvh)
Size that changes to match the current visible area. Use 100dvh for the most accurate full-height behavior that adapts as users scroll.
When to Use Each Unit
| Unit | Use Case |
|---|---|
100dvh | General full-height layouts that should always fit the visible screen |
100lvh | Content that should extend under the browser chrome |
100svh | UI elements that must always remain visible, regardless of scroll position |
The 100dvh unit is particularly valuable because it dynamically adjusts as the browser chrome expands and collapses, ensuring your layout always matches the current visible viewport.
The DEV Community explanation of the dvh unit provides additional context on how it solves the mobile viewport problem.
Code Implementation
Here are practical code examples for implementing full-height layouts that work correctly on mobile browsers.
1/* Modern full-height solution */2.full-height-element {3 min-height: 100vh;4 min-height: 100dvh;5}6 7/* Alternative with explicit fallback */8.hero-section {9 height: 100vh; /* Fallback for older browsers */10 height: 100dvh; /* Modern dynamic viewport */11}12 13/* For sticky elements that must stay visible */14.sticky-footer {15 position: fixed;16 bottom: 0;17 height: 100svh; /* Ensures content is always accessible */18}1/* Combine with safe area insets for notched devices */2.safe-full-height {3 min-height: 100dvh;4 min-height: calc(100dvh - env(safe-area-inset-bottom));5 padding-bottom: env(safe-area-inset-bottom);6}Browser Support and Compatibility
The dynamic viewport units (dvh, svh, lvh) are supported in modern browsers but require consideration for older browser versions.
| Browser | Version | Support |
|---|---|---|
| Chrome/Edge | 108+ | Full Support |
| Safari | 16+ | Full Support |
| Firefox | 109+ | Full Support |
| iOS Safari | 16+ | Full Support |
| Chrome Android | 108+ | Full Support |
1/* Progressive enhancement approach */2.component {3 /* Fallback for older browsers */4 min-height: 100vh;5 6 /* Modern browsers: use dynamic viewport */7 min-height: 100dvh;8 9 /* Legacy WebKit support (optional, for older iOS) */10 min-height: -webkit-fill-available;11}Best Practices for Mobile Full-Height Layouts
Avoid Mixing Units
Stick to one viewport unit type within a component to avoid layout shifts when the browser chrome changes state. Mixing 100vh and 100dvh can cause jarring visual changes as the user scrolls.
Test Across Scenarios
Test your layouts in these scenarios:
- Page load (chrome visible)
- After scrolling (chrome collapsed)
- While scrolling (chrome in transition)
- With virtual keyboard open
- With browser developer tools device emulation
Performance Considerations
The dynamic viewport units update in real-time as the browser chrome changes, which can trigger layout recalculations. For complex layouts, test performance on lower-end devices to ensure smooth scrolling behavior.
For teams implementing these techniques in production applications, our web development team can help ensure your layouts work flawlessly across all devices and browsers.
Frequently Asked Questions
Common Questions About 100vh on Mobile
Conclusion
The mobile 100vh issue has plagued web developers for years, but modern CSS finally provides a proper solution. By understanding the difference between large, small, and dynamic viewport units, you can create full-height layouts that work correctly across all devices.
The 100dvh unit specifically addresses the problem by dynamically matching the current visible viewport, eliminating the need for workarounds and vendor-prefixed properties.
As browser support continues to improve, there's no reason to rely on legacy solutions. Implement the modern approach today with proper fallbacks, and your mobile users will finally see your full-screen designs exactly as intended.
Related Resources: