The viewport is the visible area of a web page inside the browser window โ not the whole page, just the part currently on screen. Scroll down and the content moves, but the viewport itself stays the same size unless the user resizes the window or rotates their phone. Getting this concept right is the foundation of writing CSS that works on a phone, a tablet, and a 27-inch monitor without three separate stylesheets.
Layout Viewport vs Visual Viewport
Browsers actually track two viewports. The layout viewport is what CSS measures against โ it's the box your percentages, media queries, and vw/vh units are calculated from. The visual viewport is what's actually visible right now, which shrinks when a user pinch-zooms in or when the on-screen keyboard pops up on mobile. Most of the time you only need to think about the layout viewport, but the visual viewport is why elements sometimes seem to hide behind a mobile keyboard.
The Meta Viewport Tag
Without one line of markup, mobile browsers used to render pages at a fake desktop width โ usually 980px โ and shrink the result to fit the screen, making text microscopic. The fix is this tag in your <head>:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
width=device-width tells the browser to set the layout viewport to the device's actual width instead of that 980px default. initial-scale=1.0 sets the starting zoom to 100%. Skip this tag and every responsive CSS trick you write is wasted on mobile โ it's arguably the single most important line in a responsive project.
Viewport Units: vw, vh, vmin, vmax
Once the viewport is set up correctly, you can size elements directly against it:
1vw= 1% of the viewport's width1vh= 1% of the viewport's height1vmin= 1% of whichever is smaller, width or height1vmax= 1% of whichever is larger, width or height
These are what let you build a hero section that always fills the screen (height: 100vh) or text that scales smoothly with the window (font-size: 4vw).
Converting Between px and Viewport Units
The formulas are straightforward once you know the viewport size you're designing for:
vw = px รท viewport width ร 100vh = px รท viewport height ร 100px = vw ร viewport width รท 100
For example, a 72px heading in a 1440px-wide desktop mockup is 72 รท 1440 ร 100 = 5vw. Here's what that same 5vw becomes on other screens:
| Viewport width | Device example | 5vw in px | 50vw in px |
|---|---|---|---|
| 360px | Small phone | 18px | 180px |
| 390px | Phone | 19.5px | 195px |
| 768px | Tablet (portrait) | 38.4px | 384px |
| 1280px | Laptop | 64px | 640px |
| 1440px | Desktop mockup | 72px | 720px |
| 2560px | Large monitor | 128px | 1280px |
The table shows the double-edged nature of viewport units: 5vw is a sensible heading on a laptop, a bit small on a phone, and huge on a wide monitor. That's why pure vw sizing usually needs limits, covered below. The VW to PX converter is handy for checking a value at a specific width.
Viewport Units vs Percentages
Viewport units always measure the browser window, no matter how deeply an element is nested. Percentages measure the parent element. A width: 50% card inside a 400px sidebar is 200px; a width: 50vw card in the same sidebar is half the window and will overflow. As a rule, use percentages to fit content inside its container and viewport units for things that relate to the screen itself. See Percent to PX for how percentages resolve.
The Mobile 100vh Problem
On mobile Safari and Chrome, 100vh is measured against the maximum possible viewport height, including the space hidden behind the browser's address bar. The result: a section set to height: 100vh often extends further than what's actually visible, cutting content off at the bottom. Newer dvh (dynamic viewport height) units fix this by tracking the real, current visible height as the browser UI shows or hides. For a full-screen mobile section today, pair both so older browsers still get a fallback: height: 100vh; height: 100dvh;
svh, lvh, and dvh compared
| Unit | Measures | Best for |
|---|---|---|
svh | Smallest viewport, with browser toolbars fully shown | Content that must always be fully visible, like a call-to-action at the bottom of a hero |
lvh | Largest viewport, with toolbars hidden | Backgrounds where being slightly cut off is acceptable |
dvh | Current viewport, updating as toolbars move | Full-screen app shells and modals |
vh | Behaves like lvh in modern mobile browsers | Desktop layouts, or as a fallback |
Because dvh changes while the user scrolls, it can cause content below it to shift as the toolbar collapses. For most hero sections, svh is the calmer choice: it never overflows the visible screen and never moves.
Fluid Typography Without Losing Control
Sizing text purely in vw has two problems: it gets too small on phones and too large on wide monitors, and it doesn't respond to the user's preferred font size setting. The fix is clamp(), combining a rem minimum, a vw-based preferred value, and a rem maximum:
h1 {
font-size: clamp(2rem, 1.25rem + 3vw, 4rem);
}
On a 390px phone, 1.25rem + 3vw is 20px + 11.7px = 31.7px, so the 2rem (32px) minimum applies. On a 1440px screen it's 20px + 43.2px = 63.2px, which sits within the range. The 4rem (64px) cap only kicks in on screens wider than about 1467px. Mixing rem into the middle value means the heading still grows when a user raises their default font size, which matters for accessibility.
Common Viewport Mistakes
- Using
width: 100vwfor full-width sections. On desktop, vw includes the vertical scrollbar, so the element ends up slightly wider than the visible area and a horizontal scrollbar appears.width: 100%is usually what you want. - Disabling zoom in the meta tag. Adding
maximum-scale=1oruser-scalable=nostops people with low vision from zooming in. Leave zoom enabled. - Fixed
height: 100vhon content-heavy sections. If the content is taller than a short landscape phone screen, it overflows. Usemin-heightinstead so the section can grow. - Using vw or vh in print styles. A printed page has no browser window, so results are unpredictable. Override them in
@media print.
Frequently Asked Questions
How do I get the viewport size in JavaScript?
window.innerWidth and window.innerHeight give the layout viewport including scrollbars, which matches how vw and vh are calculated. document.documentElement.clientWidth excludes the scrollbar. For the visual viewport, use window.visualViewport.width and .height.
Do media queries use the viewport width?
Yes. @media (min-width: 768px) checks the layout viewport width in CSS pixels, which is why the meta viewport tag must be present for media queries to work as expected on phones.
What is the difference between vmin and vmax?
On a 390 ร 844px portrait phone, 1vmin is 3.9px (1% of the smaller side, the width) and 1vmax is 8.44px (1% of the height). Rotate to landscape and the values stay the same, because the smaller and larger sides simply swap.
Are container query units a replacement for viewport units?
For components, often yes. Units like cqw measure a container rather than the window, so a card can size its text based on the space it actually has. Viewport units are still the right tool for page-level things like full-screen sections.
Try it yourself: need to translate a fixed pixel value into a viewport unit for a specific screen size? Try our PX to VH and PX to VW converters, and see the CSS Units Complete Guide for how vw and vh compare with every other unit.
