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>
Note: Avoid width: 100vw for full-bleed sections in normal page flow - vw includes the width of the scrollbar, so 100vw can be a few pixels wider than the visible page and trigger a horizontal scrollbar of its own. width: 100% does not have this problem.
  • 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>
Unit or propertyRelative toCommon useGotcha
height: 100%The parent's height (which must already be explicitly set)Filling a container that has a defined sizeDoes nothing if any ancestor lacks a defined height
height: 100vhThe viewport's heightFull-screen hero sectionsMobile browsers count the address bar, causing a jump on scroll
height: 100dvhThe dynamic (visible) viewport heightMobile-safe full-screen sectionsSlightly newer than vh - use it as an override, not a replacement
min-height: 100vhThe viewport's height, but the element can grow tallerFull-height sections with variable contentGenerally the safest default for page-level sections

Frequently Asked Questions

How do I make a div fill the whole screen?
Set height: 100vh and width: 100vw, where vh and vw are percentages of the viewport. Add margin: 0 on 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 100vh is taller than the space you can actually see. Use 100dvh (dynamic viewport height), which shrinks and grows as the bar hides and reappears.