The 100vh Trap: Why Scrollable Pages Need `min-height`, Not `height`
This is a classic CSS gotcha that trips up developers of all levels, especially when building scrollable interfaces in frameworks like React, Vue, or any mobile environment. Understanding the difference between `height` and `min-height` is fundamental to creating layouts that behave predictably with dynamic content, and it directly impacts user experience by preventing visual glitches like missing backgrounds.
A developer debugging a WeChat Mini Program list page found that `height: 100vh` on the list container caused the background color to only fill the first screen. Scrolling down revealed a white background on the remaining items.
The root cause is that `100vh` is a fixed value equal to the viewport height. It does not account for content that exceeds one screen. The container is locked to that height, so any overflow content falls outside the container's background area.
The correct solution is `min-height: 100vh`. This sets a minimum height of one screen but allows the container to expand as content grows, ensuring the background fills the entire scrollable area. A secondary fix is to also set the background on the root `page` element as a fallback for edge cases like empty states or iOS rubber-band scrolling.
The article also clarifies why `height: 100%` doesn't work: percentage heights depend on the parent's height, which is often `auto` (content-driven), causing the child to collapse. Even if the entire parent chain is set to `100%`, it ultimately resolves to the viewport height, recreating the same fixed-height problem.
The real lesson is that CSS height properties are not interchangeable; choosing between `height` and `min-height` is a structural decision that depends entirely on whether the container should be fixed or flexible.
Many developers instinctively reach for `height: 100%` as a 'full-screen' solution, but this approach is fragile because it depends on an explicit height chain, which is often missing in real-world layouts.
The distinction between 'full-page scroll' and 'local scroll' is the most important architectural decision for layout. Using the wrong height property for the wrong scroll model is a common source of bugs.
The article's debugging process — from identifying the symptom, to understanding the unit, to testing alternatives, to finding the root cause — is a model for systematic CSS problem-solving.
The fact that this issue is common enough to warrant a detailed postmortem suggests that CSS layout fundamentals are still a pain point for many developers, even in modern frameworks.