technical

Set the viewport meta tag

MetricSpot checks for <meta name=viewport>. Without it, mobile browsers render at 980px desktop width and zoom out — failing Google's mobile usability check.

What this check does

Looks for a <meta name="viewport"> tag in the page <head> and verifies it sets at least width=device-width and an initial-scale. The check fails when the tag is missing entirely or when it locks zoom (user-scalable=no, maximum-scale=1.0 — both accessibility violations).

Why it matters

Without a viewport tag, mobile browsers assume the page is desktop and render it at 980px wide, then zoom out to fit the screen. The result is unreadable: 4-pixel text, oversized images, no responsive breakpoints firing because the viewport math is wrong.

  • Google’s mobile-first indexing. Since 2021, Google primarily uses the mobile rendering of your page for ranking. A site that fails the viewport check is treated as not mobile-friendly — a ranking penalty in mobile search.
  • Core Web Vitals. LCP, CLS, and INP are all measured on mobile by default. A page with no viewport tag triggers desktop-width rendering on a phone-sized canvas, which inflates CLS and LCP.
  • User experience. Mobile traffic is 60%+ for most sites. The viewport tag is what makes responsive design work.

How to fix it

Put this in the <head>, before any CSS that depends on viewport width:

<meta name="viewport" content="width=device-width, initial-scale=1">

That’s the canonical recipe — every framework, CMS, and modern starter template ships with it. If your site doesn’t have it, the <head> template is wrong.

Common framework defaults.

  • Astro<ViewTransitions /> ships nothing implicit. Add the meta tag to your base layout’s <head>.
  • Next.js — App Router exports a viewport const from app/layout.tsx:
import type { Viewport } from "next";

export const viewport: Viewport = {
  width: "device-width",
  initialScale: 1,
};
  • WordPress — every modern theme outputs the tag in header.php. If yours doesn’t, the theme is from before 2014.
  • Vue / Nuxt / Svelte — bundled into the starter index.html.

Don’t break accessibility. Two anti-patterns block pinch-to-zoom and violate WCAG 1.4.4:

<!-- Bad — accessibility violation -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

Both prevent low-vision users from pinch-zooming text. iOS 13+ ignores user-scalable=no anyway. Don’t add either.

Native app webviews. If you’re embedding the page in an iOS WKWebView or Android WebView with its own zoom controls, you can scope the viewport to the webview-specific HTML — but the public web version still needs the standard tag.

Audit yourself:

curl -s https://yourdomain.com/ | grep -o '<meta name="viewport"[^>]*>'

Expect width=device-width, initial-scale=1. If grep returns nothing, the tag is missing.

Frequently asked questions

What’s the difference between initial-scale=1 and width=device-width?

width=device-width sets the viewport width to match the device’s CSS pixel width (375 on iPhone, 360 on most Android). initial-scale=1 sets the initial zoom level to 1.0. Both are needed — set them together.

Should I include viewport-fit=cover for iPhone notches?

Only if you’re using env(safe-area-inset-*) in CSS to push content out of the notch / dynamic island. Otherwise the default value is fine.

Does the tag affect desktop browsers?

Desktop browsers ignore the viewport meta tag entirely — they always render at the actual window width. The tag is mobile-only.

Sources

Last updated 2026-05-11