How to Make a Full Screen Section in CSS
This recipe covers how to build sections that reliably fill the full height and width of the viewport or their parent, and explains the height quirks that trip beginners up.
The percentage height problem
height: 100% only works if the element's parent already has a defined height - and that parent's parent, all the way up the chain to html. Set height: 100% on a div inside a plain body that has no explicit height, and nothing happens, because there is no defined height to be 100% of. That is exactly why beginners reach for viewport units instead: they are relative to the browser window, not to any ancestor, so they always resolve to something.
Full width is usually free
Block-level elements like div and section are width: auto by default, which already stretches them to fill their parent's content box - most of the time you do not need width: 100% at all. The place people get bitten is combining width: 100% with padding under the default box-sizing: content-box, which adds the padding on top of the 100%, overflowing the parent. The fix is box-sizing: border-box, which folds padding and border inside the stated width instead of adding to it.
Example
<!DOCTYPE html>
<html>
<head>
<style>
* { box-sizing: border-box; }
.full-width-section {
width: 100%;
padding: 40px 24px;
background: #eef2ff;
}
</style>
</head>
<body>
<div class='full-width-section'>
<p>This section fills its parent's width, padding included, thanks to border-box sizing.</p>
</div>
</body>
</html>Full height with viewport units
height: 100vh means 100% of the viewport's height, regardless of the element's content or its parent's height - useful for hero sections and full-screen intros. The catch is mobile browsers: 100vh includes the space the address bar temporarily covers, so the bottom of the section can end up hidden until the bar hides on scroll, causing a visible jump. The modern fix is 100dvh (dynamic viewport height), which recalculates as the browser's own UI shows or hides.
Example
<!DOCTYPE html>
<html>
<head>
<style>
html, body { margin: 0; }
.section {
height: 100vh;
height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
color: white;
}
.section:nth-child(1) { background: #2563eb; }
.section:nth-child(2) { background: #16a34a; }
.section:nth-child(3) { background: #dc2626; }
</style>
</head>
<body>
<div class='section'>Section One</div>
<div class='section'>Section Two</div>
<div class='section'>Section Three</div>
</body>
</html>- Use min-height: 100vh instead of height: 100vh when a section's content might be taller than the screen, so it can grow instead of clipping.
- Pair height: 100vh with height: 100dvh underneath it - modern browsers use the second line, older ones fall back to the first.
- For a page with a header, scrollable content, and a footer pinned to the bottom, make body a flex column with min-height: 100vh and give the main content flex: 1.
Example
<!DOCTYPE html>
<html>
<head>
<style>
html, body { margin: 0; height: 100%; }
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
header, footer { background: #1f2937; color: white; padding: 16px; }
main { flex: 1; padding: 24px; }
</style>
</head>
<body>
<header>Site Header</header>
<main>Main content grows to fill any leftover space.</main>
<footer>Footer stays at the bottom even with little content.</footer>
</body>
</html>Frequently Asked Questions
- How do I make a div fill the whole screen?
- Set
height: 100vhandwidth: 100vw, wherevhandvware percentages of the viewport. Addmargin: 0on the body, since the default body margin otherwise pushes the section past the edge and creates a scrollbar. - Why does 100vh cut off on mobile?
- Mobile browsers count the address bar as part of the viewport, so
100vhis taller than the space you can actually see. Use100dvh(dynamic viewport height), which shrinks and grows as the bar hides and reappears.