albert.walickihire me
← all solutions
css

How to make an element 100% of the screen height?

Make an element fill the screen height with min-height: 100dvh, understand svh, lvh and dvh on mobile, and fix height: 100% that does nothing.

Use min-height with viewport units. Write 100vh first as a fallback, then 100dvh, which fixes the height on mobile browsers:

.hero {
  min-height: 100vh;
  min-height: 100dvh;
}

Browsers that understand dvh use the second line. Any browser that doesn't simply ignores it and keeps 100vh. Today every major browser supports the new units, so the fallback is only a safety net; see Can I Use.

Why 100vh is too tall on phones

On desktop, 100vh is exactly the height of the browser window. On mobile, the address bar and toolbar slide away as you scroll, so the visible area changes height. Browsers decided that vh means the largest size, with the toolbars hidden.

When the page first loads, the toolbars are visible, so an element with height: 100vh is taller than the screen. The bottom of your hero, often the call-to-action button, is hidden behind the toolbar.

The newer units describe each state:

  • svh (small viewport height): the height with the toolbars visible. The element always fits on the screen.
  • lvh (large viewport height): the height with the toolbars hidden. Same as vh on mobile.
  • dvh (dynamic viewport height): the current height. It changes while the toolbars move.

On desktop, where nothing slides in or out, all of them are the same.

svh or dvh

dvh sounds perfect, but because it follows the toolbar, the element resizes while the user scrolls. On a long page, that makes the content below it jump.

For a hero section at the top of a scrolling page, svh is a safe choice. The whole hero is visible on load, and nothing jumps later. When the toolbars hide, there's a bit of the next section showing, which is fine:

.hero {
  min-height: 100vh;
  min-height: 100svh;
}

I use dvh for layouts that fill the screen and don't scroll the page, like a full-screen app shell or a chat view where the message input has to stay at the bottom.

You may still find min-height: -webkit-fill-available in older answers. It was a workaround for iOS before these units existed and isn't needed any more.

min-height, not height

Use min-height rather than height. With a fixed height: 100dvh, content that doesn't fit overflows the element and overlaps the next section. That happens more often than you'd think: a small phone in landscape, a long headline in another language, or someone who has increased their text size. min-height fills the screen when there's little content and grows when there's more.

Why height: 100% does nothing

height: 100% means "100% of the parent's height". If the parent's height is auto, which is the default, there's nothing to take a percentage of, so it's ignored. For an element directly in <body> to be full height this way, every ancestor needs an explicit height:

html,
body {
  height: 100%;
}

In a React or Next.js app, there's usually one more wrapper in between: #root in a Vite or Create React App project, and #__next in the Next.js Pages Router. It needs the same rule, otherwise the chain breaks there. The Next.js App Router renders your layout straight into <body>, so there's no extra wrapper.

A min-height on the parent doesn't count either. body { min-height: 100% } still leaves children with height: 100% at their content height. That's why I skip the chain and put min-height: 100dvh on the element that needs it.

If you want the footer to stay at the bottom on short pages, that's a separate layout problem; see how to keep the footer at the bottom of the page.

The same problem with 100vw

width: 100vw has a related gotcha on desktop browsers with classic scrollbars, like on Windows. The viewport width includes the vertical scrollbar, so an element with 100vw is wider than the page and causes a horizontal scrollbar. For full width, width: 100% on a block element is usually what you want.

more solutions
work with me

Got something that needs building?

Frontend builds, full-stack features in Django, design-system work. Available for work.

See my workGet in touch