The viewport meta tag tells a mobile browser how to size and scale the page's layout viewport. Add it in the document head, keep zoom available, and test the deployed page at narrow widths. The tag gives responsive CSS the viewport it expects, but it does not repair fixed-width components or prove that the page works on mobile.
This guide covers a safe baseline, common mistakes, production checks, and a focused Playwright test for developers preparing a website launch.
Viewport meta tag checklist
Use this sequence for every public HTML template:
- Add one viewport meta tag inside
head. - Set
width=device-widthso the layout viewport follows the device width. - Use
initial-scale=1when you want the initial zoom level stated explicitly. - Do not disable user zoom with
user-scalable=noor a restrictivemaximum-scale. - Keep images, tables, code blocks, dialogs, and controls inside the viewport.
- Inspect the initial HTML response as well as the rendered DOM.
- Test at the smallest width the product supports and in both orientations where relevant.
- Put stable source and overflow assertions in CI.
- Repeat the deployed check after release.
The tag is an input to responsive layout, not a complete mobile test.
What the viewport meta tag does
Mobile browsers may use a virtual layout viewport wider than the physical screen and then shrink the result. That compatibility behavior helped older desktop-only pages fit on phones, but it can make responsive text and controls appear very small. MDN's `meta name="viewport"` reference explains how the tag supplies hints for the viewport's width and scaling behavior.
For a responsive page, start with:
<meta name="viewport" content="width=device-width, initial-scale=1">
width=device-width asks the browser to match the layout viewport to the screen width in CSS pixels. initial-scale=1 asks for a 1:1 initial scale. Google's responsive web design basics shows the same baseline and explains why pages without it can load as a zoomed-out desktop layout.
The viewport meta tag does not make a page responsive by itself. CSS still controls whether a grid collapses, an image shrinks, a table scrolls inside its own container, or a dialog fits on screen. Treat the tag and the rendered layout as two separate release checks.
Add the viewport meta tag to the document head
Put the tag in the shared document template that owns head, next to the character encoding and page title:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Acme developer portal</title>
</head>
<body>
<main>...</main>
</body>
</html>
Every HTML entry point needs the declaration. A single-page application normally owns it in the root HTML file. A server-rendered or statically generated site should put it in the document or layout component shared by all routes.
Do not add a second tag from a route component or client effect. Keep one reviewed source of truth. If a framework already emits the declaration, inspect the built HTML before adding another copy.
Avoid a fixed value such as width=1024. A fixed mobile viewport can preserve a desktop layout at the cost of small text, misleading media-query behavior, and extra zooming. Use CSS constraints for component widths instead:
.page-shell {
width: min(100% - 2rem, 72rem);
margin-inline: auto;
}
img,
video {
max-width: 100%;
height: auto;
}
The website image optimization checklist covers responsive image markup, intrinsic dimensions, formats, and layout-shift checks in more detail.
Keep viewport zoom available
Do not use the viewport meta tag to prevent visitors from zooming:
<!-- Avoid these restrictions. -->
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
>
People with low vision may rely on browser zoom to read text or inspect controls. MDN warns that user-scalable=no can prevent people from enlarging content, and the W3C guidance for WCAG 2.2 Success Criterion 1.4.4 explains the requirement for text to resize without loss of content or functionality.
Keep the baseline simple unless the product has a tested reason for another directive. Optional values such as viewport-fit=cover affect how a page uses displays with cutouts. When using that value, apply the browser-provided safe-area inset variables so important content and controls do not sit under device hardware or browser UI. Test the actual supported devices and orientations rather than assuming the directive is enough.
Fix mobile overflow after setting the viewport
Once the browser uses the intended mobile viewport, layout bugs that were hidden by desktop-width scaling can become obvious. Typical causes include:
- a component with a large fixed or minimum width;
- an image, video, SVG, or iframe wider than its container;
- a long URL or code sample that cannot wrap or scroll locally;
- a table that forces the entire document wider;
- an absolutely positioned control outside its containing block; and
- a modal or cookie banner sized from desktop assumptions.
Do not hide the symptom with body { overflow-x: hidden; }. That can make off-screen content impossible to reach while leaving the broken geometry in place. Find the widest element and constrain the component that owns it.
In browser developer tools, compare the document width with the viewport width:
({
viewportWidth: document.documentElement.clientWidth,
documentWidth: document.documentElement.scrollWidth,
})
The document width should not exceed the viewport width for a page designed without horizontal document scrolling. Test purposeful horizontal regions, such as code samples or data tables, separately and make sure their scroll area is visible and keyboard reachable.
Use the broader mobile website testing guide to exercise navigation, forms, content order, and the main visitor task. Then use the touch target size guide to measure controls rather than judging them from a screenshot.
Test the viewport meta tag in production
Check the deployed response first. This catches a tag missing from the production template even when a development shell contains it:
curl -sS https://example.com/ \
| grep -i -m1 "name=['\"]viewport['\"]"
Then inspect the rendered document:
document
.querySelector('meta[name="viewport"]')
?.getAttribute("content")
Record the public URL, viewport width and height, orientation, browser, and whether the page was tested with a clean cache. At a minimum, verify:
- one viewport meta tag exists in
head; - its content includes
width=device-width; - browser zoom remains available;
- the document does not scroll horizontally;
- visible controls remain fully inside the viewport;
- dialogs and menus stay usable when open; and
- text remains readable after zooming and rotating the device.
A desktop browser's responsive mode is useful for repeatable debugging, but keep at least one real-device check in the release process when device browser UI, display cutouts, or the on-screen keyboard affect the task.
Add a viewport meta tag test to Playwright
Use a known narrow viewport and assert both the declaration and the rendered document width. Playwright documents viewport configuration in its emulation guide.
import { expect, test } from "@playwright/test";
test.use({ viewport: { width: 375, height: 812 } });
test("page declares and fits the mobile viewport", async ({ page }) => {
await page.goto("https://example.com/");
const content = await page
.locator('meta[name="viewport"]')
.getAttribute("content");
expect(content).toMatch(/(?:^|,)\s*width\s*=\s*device-width\b/i);
const dimensions = await page.evaluate(() => ({
viewportWidth: document.documentElement.clientWidth,
documentWidth: document.documentElement.scrollWidth,
}));
expect(dimensions.documentWidth).toBeLessThanOrEqual(
dimensions.viewportWidth + 1,
);
});
The one-pixel tolerance avoids noise from fractional layout rounding. It should not excuse a genuinely off-screen component. Add route-specific assertions for the navigation, primary action, forms, and open overlays whose behavior matters to the release.
Run the test against a deployed preview or production URL as well as local code. The website audit with GitHub Actions guide shows how to keep public-URL checks and their evidence in a pull request, while the website regression testing checklist explains how to preserve a stable baseline.
Check the viewport meta tag with Slop Audit
Run a Slop Audit on the deployed page after publishing the viewport configuration. Slop Audit checks the initial public HTML for a viewport meta tag. When Browser Run capacity is available, it also renders the page at a 375 by 812 mobile viewport, compares document width with viewport width, and counts visible controls that are clipped or horizontally off screen.
Those checks answer bounded release questions: was the tag present in the tested response, did the rendered document overflow at the measured width, and were visible controls outside the mobile viewport? They do not prove every viewport directive is appropriate, test all devices or orientations, open every interactive state, guarantee accessibility, or certify the complete responsive design. Keep route-specific CI tests and manual task review beside the scan.
Viewport meta tag release sign-off
- One viewport meta tag appears in the head of every public HTML entry point.
width=device-widthgives responsive CSS the intended layout viewport.- Browser zoom is not disabled or artificially restricted.
- The smallest supported width has no unintended document-level horizontal scroll.
- Navigation, forms, dialogs, and the primary action remain inside the viewport.
- Purposeful scrolling regions work without making the whole page wider.
- The deployed response and rendered DOM agree.
- CI covers stable routes, and the public URL is checked again after release.
The viewport meta tag is a small part of the page shell with a large effect on mobile rendering. Configure it once, test the layout it enables, and keep the production evidence with the release.