viewport meta

Viewport Meta — Live Demos

With vs without the viewport tag

The same responsive page on a phone — with the tag (fits the screen) and without it (rendered at ~980px and scaled down).

W3Tweaks
Advanced HTML Tutorials — learn dialog, popover, view transitions and more with live demos.
Every tutorial ships an interactive demo. Read more
Responsive, accessible, fast.
❌ No viewport tag
Rendered at 980px, scaled down — tiny & unreadable
W3Tweaks
Advanced HTML Tutorials — learn with live demos.
Every tutorial ships an interactive demo. Read more
✅ With viewport tag
Fits the device width — readable, responsive
<!-- without this, mobile assumes ~980px and scales down --> <meta name="viewport" content="width=device-width, initial-scale=1">
--:--:--Left: no tag (980px scaled). Right: proper device-width.

Accessible viewport tag builder

Toggle properties and get a live accessibility verdict. The builder flags any setting that fails WCAG 1.4.4.

width=device-width (always on)
initial-scale=1
viewport-fit=cover (notch)
interactive-widget=

⚠ ACCESSIBILITY-BREAKING (for demo)
user-scalable=no
maximum-scale=1
Generated tag
--:--:--Toggle user-scalable=no to see the accessibility failure

Notch & safe areas — viewport-fit=cover + env()

Toggle viewport-fit=cover and the env(safe-area-inset-*) padding to see how content clears the notch and home indicator.

viewport-fit=cover (draw edge-to-edge)
apply env(safe-area-inset-*) padding
☰ Header
Content area
Bottom nav
--:--:--Turn env() padding off to see the header hide behind the notch

Dynamic viewport units — the 100vh bug

A hero set to 100[unit] with the mobile address bar. Toggle the bar and switch units to see which overflow, gap, or track.

100vh (legacy)
100svh
100lvh
100dvh
address bar: visible
🔒w3tweaks.com
100vh hero
↓ content below the hero
--:--:--Switch to svh — the hero always fits; try vh with the bar visible

Live visualViewport readout

The visualViewport API reports the actually-visible area. Resize this window, pinch-zoom, or (on mobile) focus the input and watch the values change in real time.

visualViewport.width
visualViewport.height
visualViewport.scale (zoom)
window.innerHeight
const vv = window.visualViewport; vv.addEventListener('resize', () => { // fires on keyboard open/close & pinch-zoom console.log(vv.height, vv.scale); });
Compare visualViewport.height to window.innerHeight: when the keyboard opens on mobile, the visual height shrinks but innerHeight (and dvh) often don't — which is why keyboard-aware layouts need this API.
--:--:--Resize the window or pinch-zoom to see live updates