Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

CSS  Module 5 – Values, units and math functions

Viewport units: vw, dvh, svh and lvh

How vw, vh, svh, lvh and dvh measure the viewport, why 100vh hides content behind phone toolbars and 100vw overflows, and what to use instead.

  • Intermediate
  • 20 minutes
  • Examples run with Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free core, Pro depth: 8 of 20 minutes free
Free: Viewport heights follow one of three toolbar states · Choose a stable hero or a shell that follows toolbars. With a pass: 2 in-depth parts and 3 interview answers, about 12 minutes.

What you will learn

  • Size full-screen sections with svh, lvh and dvh instead of 100vh on mobile
  • Use vi and vb logical viewport units and know when vw causes horizontal overflow
  • Avoid viewport-only font sizes that stop text growing when the user zooms

Before you start

What you’ll learn · Before you start

What you will learn

  • Size full-screen sections with svh, lvh and dvh instead of 100vh on mobile
  • Use vi and vb logical viewport units and know when vw causes horizontal overflow
  • Avoid viewport-only font sizes that stop text growing when the user zooms

Before you start

On this page

Viewport units size things as a share of the browser’s viewport: A viewing or layout reference area used by the browser; a viewport-based length names which size and direction supply its reference.: vw is 1 % of its width and vh 1 % of its height, so 100vh is one full screen. Phones complicate the height, because their browsers show toolbars when a page opens and hide them while the reader scrolls. CSS therefore has three viewport heights. svh measures the small viewport: The viewport-size reference associated with the browser's retractable interface being expanded., with the toolbars shown. lvh measures the large viewport: The viewport-size reference associated with the browser's retractable interface being retracted., with them hidden. dvh measures the dynamic viewport: A viewport-size reference that follows the browser's current retractable-interface state., whichever of the two is on screen right now. Plain vh is the large one, so a 100vh section can sit partly behind the toolbars. Use svh for full-screen sections, dvh for app shells that must match the visible area, and 100% rather than 100vw for full widths, because vw includes a desktop scrollbar. The supplied comparison cases below use Chromium 153, Firefox 155 and WebKit 26.6.

Viewport heights follow one of three toolbar states

The viewport is the part of the window that shows the page. On a desktop its height changes only when the window does. On a phone the browser’s address bar and buttons slide away as the reader scrolls down, so the space for the page grows, and they come back on scrolling up. CSS Values 4 names the two extremes and the moving value between them:

  • svh (small) assumes every retractable toolbar is shown: content this tall always fits, with a gap below once the toolbars hide.
  • lvh (large) assumes they are all hidden: content this tall fills the screen once they hide, but the toolbars cover part of it while they show.
  • dvh (dynamic) follows the toolbars, so it always matches the visible area, and changes while the reader scrolls.

vh was defined before phones did this, and browsers settled on the large viewport for it, so vh means lvh. Each height unit has width and logical twins (svw, dvi, lvmin and so on); on most phones the toolbars change only the height, so the width variants agree. The small, large and dynamic units are Baseline widely available. The numbers of a phone differ from model to model and browser to browser, so the program takes one example, a viewport 640 px tall with 56 px of toolbars:

Four heights on a phone with toolbars JavaScript · toolbars.mjs
// The small, large and dynamic viewport heights of CSS Values 4 on a phone whose browser shows its toolbars when the
// page opens and hides them while the reader scrolls. The heights are an example: every phone and browser has its own.

const viewport = { largeHeight: 640, toolbars: 56 };   // CSS px: the viewport with the toolbars hidden, their height
const smallHeight = viewport.largeHeight - viewport.toolbars;

const units = {
  '100vh': () => viewport.largeHeight,                   // vh is the large viewport
  '100lvh': () => viewport.largeHeight,
  '100svh': () => smallHeight,
  '100dvh': (shown) => (shown ? smallHeight : viewport.largeHeight),
};

console.log('unit     toolbars shown          toolbars hidden');
for (const [unit, height] of Object.entries(units)) {
  const row = [true, false].map((shown) => {
    const visible = shown ? smallHeight : viewport.largeHeight;
    const h = height(shown);
    const note = h > visible ? `${h - visible}px hidden` : h < visible ? `${visible - h}px gap below` : 'fits exactly';
    return `${h}px, ${note}`.padEnd(24);
  });
  console.log(`${unit.padEnd(8)} ${row.join('')}`.trimEnd());
}

// A full-screen hero with its 48px button at the bottom: is the button visible when the page opens?
for (const unit of Object.keys(units)) {
  const heroHeight = units[unit](true);
  const buttonTop = heroHeight - 48;
  console.log(`hero at ${unit}: button from ${buttonTop}px to ${heroHeight}px, ${heroHeight <= smallHeight ? 'visible' : 'behind the toolbars'} on opening`);
}

Output

unit     toolbars shown          toolbars hidden
100vh    640px, 56px hidden      640px, fits exactly
100lvh   640px, 56px hidden      640px, fits exactly
100svh   584px, fits exactly     584px, 56px gap below
100dvh   584px, fits exactly     640px, fits exactly
hero at 100vh: button from 592px to 640px, behind the toolbars on opening
hero at 100lvh: button from 592px to 640px, behind the toolbars on opening
hero at 100svh: button from 536px to 584px, visible on opening
hero at 100dvh: button from 536px to 584px, visible on opening

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node toolbars.mjs

A phone with toolbars shown has a 584 px small viewport; with them hidden, a 640 px large one. dvh follows whichever is showing.When the page opens: toolbars shownWhile the reader scrolls: toolbars hiddenbrowser toolbars: 56 pxvisible page: 584 px100svh = 100dvh = 584 px, fits100vh = 100lvh = 640 px,56 px behind the toolbarsvisible page: 640 px100vh = 100lvh = 100dvh = 640 px, fits100svh = 584 px,a 56 px gap below itscrolling hides the toolbars

The small, large and dynamic viewport of one example phone

Text description of the diagram

The diagram follows the lesson's example phone, whose viewport is 640 px tall with the browser's toolbars hidden and 584 px tall while they show. Real phones and browsers have their own numbers.

  1. When the page opens, the toolbars are shown and take 56 px. The visible page is 584 px tall: the small viewport. 100svh and 100dvh are both 584 px and fit exactly. 100vh and 100lvh are 640 px, the large viewport, so 56 px of a box that tall sits behind the toolbars.
  2. Scrolling hides the toolbars, and the visible page becomes 640 px tall: the large viewport. Now 100vh, 100lvh and 100dvh are 640 px and fit. 100svh stays 584 px, leaving a 56 px gap below the box.
  3. So svh never hides content, lvh and vh never leave a gap, and dvh changes with the toolbars, which makes boxes sized with it resize while the reader scrolls.

A 100vh hero opens with its bottom 56 px behind the toolbars, which is often where its main button goes. 100svh fits on opening and leaves a 56 px gap once the toolbars hide. 100dvh always fits, at a cost the specification spells out: a box sized in dynamic units resizes while the reader scrolls, which can be distracting and costs layout work on every change. Browsers may also skip the in-between values while the toolbars animate. The on-screen keyboard usually doesn’t count as a toolbar: the specification gives it as the typical example of an interface that overlays the page without changing any viewport unit. A chat page that needs its input above the keyboard can ask for interactive-widget=resizes-content in its viewport <meta> tag, which resizes the viewport, and every viewport unit with it, in the browsers that support that key.

Follow the same 640px phone through the two toolbar states. The steps use the programme’s 56px toolbar value rather than assuming every phone has that much browser interface:

Interactive · step by step Four height units across two toolbar states Follow the 640px phone and its 56px toolbars from toolbars.mjs.
Four height units across two toolbar states, step 4 of 4. Showing Visible height (640 px after scrolling), vh and lvh, svh, dvh (640 px after scrolling). In focus: svh, dvh.Visible height640 px after scrollingvh and lvh640 pxsvh584 pxdvh640 px after scrolling

The drawing shows the whole scene; its 4 steps are listed below.

Every step as text
  1. Toolbars show. The 56px toolbars leave 584px visible. vh and lvh still use 640px, while svh and dvh use 584px in this opening state.
  2. Place the 48px button. A button at the bottom of a 640px hero runs from 592 to 640px, behind the toolbar boundary. A 584px hero puts it from 536 to 584px.
  3. Toolbars hide. The visible height becomes 640px. The dynamic reference follows it, while the small reference stays at 584px and leaves a 56px gap.
  4. Choose the change you need. The references describe different behaviours. A stable hero can use the small height; a shell that must follow the current height can use the dynamic one.

The small and large references stay at 584 and 640px. Only the dynamic reference changes with the toolbar state.

Checkpoint

Check: Small large and dynamic heights

  1. Question 1 of 2 The model phone has a 640px large height and 56px of shown toolbars. How tall is 100svh?

    Type a number.

    Show the answer: Question 1 of 2

    Answer: 584 px

    The small reference is 640 - 56 = 584px and does not change when the toolbars hide.

  2. Question 2 of 2 After the model phone's toolbars hide, how tall is that same 100svh box?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 584 px

    svh keeps the small reference rather than changing to the now-visible large height.

Choose a stable hero or a shell that follows toolbars

Start with the required behaviour rather than the newest unit. A hero should keep its main action in view when browser toolbars are expanded, then stay steady during a scroll. A shell can instead require its navigation to follow the current available height. These goals select different references even on the same phone.

The fallback uses declaration order. Put the large-reference vh declaration first and the small-reference svh declaration second. An engine that understands both selects the later one; an older engine discards the unfamiliar value and retains the earlier declaration. Reversing those lines would override the small-reference choice.

Which full-screen height?
Criterion vh, lvhsvhdvh
Measures The large viewportThe small viewportWhat is visible now
Toolbars shown Bottom hidden behind themFitsFits
Toolbars hidden FitsGap belowFits
Resizes while scrolling NoNoYes
When to choose Backgrounds that may run under the toolbarsHeroes and full-screen sectionsApp shells, chats, maps

For widths, prefer 100% or a grid that spans the page to 100vw; use vi and vb when a component may meet vertical text; and never size text in viewport units alone.

What Is My Screen Resolution? See the size of your browser's viewport in CSS pixels, and how zooming changes it and the device pixel ratio.

Checkpoint

Check: Choosing a stable or changing height

  1. Question 1 of 2 Which declaration comes last in the hero's fallback pattern?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: min-block-size of 100svh

    Equal-specificity declarations use their order when both values are understood.

  2. Question 2 of 2 Which reference should a shell follow when its bottom navigation must move with the changing toolbar state?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: dvh

    Choose the reference from the required behaviour, then handle content and scrolling separately.

Fit complete shells and full-width layouts Pro: opens with a Pro, Premium or Ultimate pass

The height reference is only one part of a working layout. These cases follow content growth, the scrolling row and the width left beside a classic scrollbar.

In this part:

  • A shell gives its scrolling row room to shrink
  • Full-width grids use the available page area

1 diagram · 4 runnable examples (100vw banner, CSS, Grid banner, HTML) · about 6 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; nothing renews unless you choose to. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Follow logical axes and test zoomed text Pro: opens with a Pro, Premium or Ultimate pass

A viewport length also has an axis and a pixel scale. These cases keep both references explicit while working through vertical text and larger on-screen type.

In this part:

  • Logical axes change which viewport side a unit uses
  • Zoom changes CSS pixels and the viewport together
  • Practise the complete phone model
  • Work out viewport units on a phone with toolbars
    • Results of the sample tests
  • Keep the full layout cases together

2 diagrams · 2 runnable examples (HTML) · 1 exercise with sample tests · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; nothing renews unless you choose to. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Practise the viewport core

Practice that adapts to you

Practise this lesson

4 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 4 A phone's viewport is 700px tall with the browser's toolbars hidden and 620px tall while they show. The page has just opened and the toolbars show. How tall is a box with block-size: 100vh?

    Type a number.

    Show the answer: Question 1 of 4

    Answer: 700 px

    vh is defined against the large viewport, the one with every toolbar retracted, so 100vh is 700 px whether the toolbars show or not. While they show, 80 px of the box sit behind them. 100svh would be 620 px and 100dvh 620 px now and 700 px once the toolbars hide.

  2. Question 2 of 4 A full-screen hero has its main button at the bottom. Which height keeps the button visible when the page opens on a phone, without the hero resizing while the reader scrolls?

    Choose one answer.

    Show the answer: Question 2 of 4

    Answer: min-block-size: 100svh

    svh is the small viewport, measured with the toolbars shown, so a hero that tall always fits on opening, and its size is stable. vh and lvh are the large viewport and hide the bottom behind the toolbars; dvh fits too, but it changes size as the toolbars come and go.

  3. Question 3 of 4 Why write min-block-size: 100vh; before min-block-size: 100svh; in the same rule?

    Choose one answer.

    Show the answer: Question 3 of 4

    Answer: An engine that can't parse svh drops the second declaration and keeps the first

    Both declarations have the same specificity and origin, so the later one wins when the browser understands it. A browser that doesn't know svh treats that declaration as invalid and drops it at parse time, so the earlier 100vh stays. Swap them, and every engine would use 100vh.

  4. Question 4 of 4 Which reference defines plain vh in the lesson's model?

    Choose one answer.

    Show the answer: Question 4 of 4

    Answer: The large viewport

    Naming the reference predicts the opening-state difference without guessing a device height.

Interview questions

Fresher · What is the difference between 100vh, 100svh and 100dvh on a phone?

All three are a full viewport height, measured against different viewports. Phone browsers show toolbars when a page opens and hide them while the reader scrolls. 100svh is the small viewport, with the toolbars shown, so content that tall always fits, and leaves a gap once they hide. 100vh is the same as 100lvh, the large viewport with the toolbars hidden, so while they show, the bottom of the content sits behind them: 56 px of a 640 px screen in the lesson’s example, often where the main button is. 100dvh follows the toolbars and always matches the visible area, but it resizes while the reader scrolls. Use svh for heroes, dvh for app shells, and put 100vh first as a fallback.

  1. Fresher to mid

    A landing page's hero is height: 100vh with its sign-up button at the bottom. On phones the button is hidden until the visitor scrolls, and testers on desktops can't reproduce it. Explain why, fix it for current and older browsers, and say how you would test it.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    A full-width banner uses width: 100vw with margin-inline: calc(50% - 50vw) inside a centred container. Users on Windows report a horizontal scrollbar, and nobody in the team, all on Macs, can see it. Explain, fix it without vw, and stop it coming back.

    Model answer, Pro. First step and follow-ups

  3. Mid to senior

    A dashboard uses 3vw text in an 800px window. Readers say zoom barely enlarges it, even after a developer adds clamp(). How do you investigate its references, choose bounds and test that the page remains usable?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • vh and lvh use the large viewport; svh uses the small one, and dvh follows its dynamic size.
  • Choose a stable small-viewport reference for a hero and a dynamic reference for a shell that must resize with toolbars.
  • Widths and font sizes need their own reference decisions; a viewport unit does not fit every layout job.

Terms in this lesson

dynamic viewport
A viewport-size reference that follows the browser's current retractable-interface state.
large viewport
The viewport-size reference associated with the browser's retractable interface being retracted.
small viewport
The viewport-size reference associated with the browser's retractable interface being expanded.
viewport
A viewing or layout reference area used by the browser; a viewport-based length names which size and direction supply its reference.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.