Skip to content
Issue docs

Viewport meta tag missing a required directive

Importantviewport_meta_tag_incompleteIssue 31

What is this issue?

This issue fires when a page has a <meta name="viewport"> tag but its content attribute is missing one of the two directives that make it work:

  • width=device-width — match the layout width to the device screen width
  • initial-scale=1 — start at a 1:1 zoom level

A tag reading content="width=1024" or content="user-scalable=no" raises this issue; content="width=device-width, initial-scale=1" does not.

This is the "the tag is wrong" half of what used to be a single check titled Viewport meta tag missing or incomplete. It is scored below the missing-tag case because a partially configured viewport usually still renders, where no viewport at all does not.

Why it matters

A viewport tag without width=device-width pins the layout to a width you chose rather than the width the device has, so the page is scaled on every screen that is not exactly that size. A tag without initial-scale=1 leaves the initial zoom to the browser, and browsers disagree — the same page opens at different zoom levels on different devices.

  • Responsive CSS is evaluated against the viewport width. A fixed width= value makes your media queries fire against the wrong number, so breakpoints trigger on the wrong devices.
  • It reads as mobile-ready and is not. Because a tag is present, the problem survives casual review; it usually surfaces as a layout bug reported from one specific phone.

How to fix it

  1. Set the content attribute to both directives:

    <meta name="viewport" content="width=device-width, initial-scale=1" />
  2. Replace any fixed width. width=1024 (or any pixel value) should become width=device-width.

  3. Remove zoom restrictions. user-scalable=no and maximum-scale block users from zooming and are an accessibility failure; neither is needed for a responsive layout.

  4. Consolidate duplicates. If a template renders more than one viewport tag, browsers apply the last one they see. Keep exactly one.

  5. Verify. The issue payload lists which directives were absent under missing, so re-scan and confirm that list is empty.

Examples

1. A fixed pixel width

Problem — the layout is pinned to 1024px whatever the device is, so a phone renders a desktop page scaled down:

<meta name="viewport" content="width=1024" />

Reported as: missing: ["width=device-width", "initial-scale=1"]

Fixed:

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

2. Missing only initial-scale

Problem — the width is right, but the page can open at a zoom level the browser picked:

<meta name="viewport" content="width=device-width" />

Reported as: missing: ["initial-scale=1"]

Fixed:

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

3. Extra directives are fine; initial-scale=1.0 is fine

Both required directives are present in each of these, so neither raises the issue — anything else in the string is left alone.

Passes:

<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=5" />

Fails — user-scalable=no is not a substitute for either directive, and it also blocks pinch-zoom, which is an accessibility problem in its own right:

<meta name="viewport" content="user-scalable=no" />

How PixyScan detects this

  1. Tag lookup. The crawler reads the content attribute of <meta name="viewport">. If there is no such tag, this check does not apply — that is viewport_meta_tag_missing.

  2. Directive matching, case-insensitively and tolerant of whitespace:

    • width\s*=\s*device-width
    • initial-scale\s*=\s*1 (so initial-scale=1.0 passes)
  3. Pass/fail.

    • Fails when either directive is absent. The finding's missing array names which, and viewportContent records the value as written.
    • Passes when both are present, regardless of any other parameters in the string.

One issue is raised even when both directives are absent — the defect is "this tag is incomplete", and the payload says how.

What we store

Storage Level

Page Level — evaluated for each crawled URL.


Database Table / Prisma Model

PageHtmlHeadAudit

One row per crawled URL, keyed by urlId.


Fields Used

Field Type Description
viewportContent String? The content attribute as written, e.g. width=1024, user-scalable=no. This is the string the check matches against

Stored verbatim rather than reduced to a pass/fail flag, so the report can quote the page's own value back and the finding can name which of the two required directives is absent.

A null or empty value here is viewport_meta_tag_missing (#30), not this issue.


Detection Dependencies

  • HTML Document — the content attribute of <meta name="viewport"> is read from the fetched page's <head>

Further reading