When building landing pages or hero sections, a common expectation is that the first <div> inside the <body> should stretch to the full height of the viewport. Simple, right? Just slap on height: 100% and move on.
But many frontend developers quickly realize... it doesnโt work.
In this post, Iโll walk you through:
- Why this layout bug happens
- The correct way to fix it
- Real-world use cases
Bonus tip: Why :root { height: 100% } might help when html { height: 100% } doesnโt.
๐ฏ The Common Setup
A developer might start with this HTML/CSS:
<body>
<div class="main-content">Hello, World!</div>
</body>
.main-content {
height: 100%;
background: lightblue;
}
Expected: The blue background fills the screen
Actual: The content takes only as much height as its children โ definitely not 100% of the viewport.
โ Why It Doesnโt Work
Because height: 100% on .main-content means:
"Be 100% as tall as my parent"
But if neither html nor body has an explicit height,.main-contenthas no reference point to calculate that 100%.
โ The Correct Solution
Set the height of html and body to 100%:
html,
body {
height: 100%;
margin: 0;
}
body > div:first-child {
min-height: 100%;
background: lightblue;
}
๐ก min-height allows the content to grow if necessary but still ensures full viewport coverage.
๐ min-height: 100% vs 100vh
Both are valid, but behave slightly differently:
- 100vh is fixed to the viewport height (useful for hero sections).
- min-height: 100% is relative to the parentโs height (better for layouts that might grow with content. Example:
.main-content {
min-height: 100vh; /* or use 100% with proper html/body setup */
}
โ ๏ธ Bonus: When :root { height: 100% } Works But html { height: 100% } Doesnโt
In component-based frameworks (like Vue, Nuxt, or React), styles might be scoped, meaning selectors like html or body donโt apply unless explicitly defined in global CSS.
Why :root sometimes works better:
- It selects the html element but has slightly higher specificity
- Itโs less likely to be overridden by resets or scoped styles
:root {
height: 100%;
}
Use
:rootas a fallback or if youโre unsure about where your global styles are applied in your app structure.
๐ง Final Thoughts
Layout bugs like this can be frustrating, especially when the fix seems โobvious.โ But understanding inheritance, box models, and scope helps demystify these quirks.
Next time your section isnโt filling the screen, ask:
- Did I set height: 100% on both html and body?
- Is my layout in a scoped or modular system like Vue?
- Should I use :root for more reliable global styling?
Top comments (0)