How Dynamic Viewport Units Fixed Mobile Safari's Address Bar

For years, web developers struggled with mobile Safari's expanding and collapsing address bar, which caused elements sized with the traditional 100vh CSS unit to overflow the screen and hide critical content. The introduction of new CSS viewport units—specifically svh, lvh, and dvh—finally resolved this issue by giving developers precise control over how elements respond to dynamic browser interfaces. This article explains the mechanics of the original mobile Safari viewport problem and how these three modern CSS units provide a native, JavaScript-free solution.

The Problem with 100vh in Mobile Safari

Historically, the vh (viewport height) unit was designed to represent 1% of the visible screen height. Setting an element to 100vh meant it should take up the entire height of the screen. However, mobile Safari features a dynamic user interface: when a user first loads a webpage, the address bar and bottom navigation toolbar are fully visible. When the user scrolls down, these toolbars shrink or disappear to provide more reading space.

Originally, if Safari recalculated 100vh as the toolbars shrank, every element using vh units would resize during a scroll. This caused a jarring, jumpy user experience and terrible scrolling performance.

To prevent this layout shift, Apple made a controversial decision: mobile Safari permanently calculated 100vh as if the browser toolbars were always hidden. Consequently, when a user first landed on a page with the toolbars visible, any element set to 100vh was actually taller than the visible screen. This caused the bottom of the element—often containing important buttons or navigation—to be cut off or hidden behind the browser UI, forcing an unwanted scrollbar on what was meant to be a single-screen layout.

Before the new units were introduced, developers had to rely on clunky JavaScript event listeners measuring window.innerHeight to manually set heights, or inconsistent CSS hacks like -webkit-fill-available.

The Solution: svh, lvh, and dvh

To solve this permanently, the CSS Working Group introduced new viewport units that explicitly account for dynamic browser toolbars. Instead of forcing one static definition of the viewport, developers can now choose between three distinct states.

1. Small Viewport Height (svh)

The svh unit represents the "Small Viewport"—the visible screen area when all browser toolbars (like Safari's address bar) are fully expanded.

  • How it solves the problem: Setting a hero section or modal to 100svh guarantees that the element will fit entirely on the screen the moment the page loads. Nothing will be hidden behind the Safari toolbar, and no unwanted scrolling will occur. When the user scrolls down and the address bar shrinks, the 100svh element remains the exact same size, preventing any jumpy layout shifts.

2. Large Viewport Height (lvh)

The lvh unit represents the "Large Viewport"—the visible screen area when the browser toolbars are completely retracted.

  • How it solves the problem: 100lvh effectively standardizes the behavior that mobile Safari previously forced upon 100vh. It is useful for background elements or layouts where you intentionally want the element to fill the maximum possible screen space once the user begins scrolling, and you do not mind if the bottom is slightly obscured on the initial load.

3. Dynamic Viewport Height (dvh)

The dvh unit represents the "Dynamic Viewport." It is a fluid unit that automatically transitions between the svh and lvh values in real-time as the browser interface expands and collapses.

  • How it solves the problem: When a page loads in mobile Safari, 100dvh equals 100svh, fitting perfectly between the visible toolbars. As the user scrolls and the address bar shrinks, 100dvh dynamically recalculates and grows until it matches 100lvh. This ensures an element is always flush with the edges of the visible screen, regardless of the toolbar's state.

Choosing the Right Unit

While dvh sounds like the ultimate fix, it comes with a performance caveat. Because 100dvh forces the browser to recalculate the layout as the user scrolls, it can still cause visual jumping and frame drops on complex pages.

Therefore, the problem is best solved by using these units strategically:

  • Use 100dvh for fixed, non-scrolling application layouts (like a chat interface or a full-screen mobile menu) where the UI must constantly hug the bottom of the screen.
  • Use 100svh for standard scrolling web pages (like a website's top hero section). It guarantees the content fits perfectly on initial load without causing layout shifts when the user scrolls down the page.