Zooming and scaling must not be disabled

Many customers with low vision zoom in on their phone to read prices, product details and checkout fields. A viewport setting that blocks zooming (user-scalable=no or maximum-scale=1) leaves small text unreadable and can stop them from completing a purchase.

Rule id
meta-viewport
Source
axe-core 4.13.0
Impact
Moderate
Fix tier
AUTO
on Shopify, Shopware, WooCommerce and Magento
Status
runs

What the check does

Ensure <meta name="viewport"> does not disable text scaling and zooming

The rule reads the content attribute of each <meta name="viewport"> element in the top-level document. Viewport tags inside iframes are not tested, and a tag with a missing or empty content passes.

axe-core splits the content at commas and semicolons into key=value pairs, ignores letter case and the spaces around keys and values, and fails the tag in three cases:

  • user-scalable=no
  • a numeric user-scalable value greater than -1 and less than 1, such as user-scalable=0
  • a maximum-scale below 2, where maximum-scale=yes is read as 1 and a negative value is ignored

Other keys, such as width, initial-scale and minimum-scale, play no part. The failure message names the setting that blocks zooming.

The rule only reads the markup and does not zoom the page, so it cannot tell whether text stays readable at 200 percent. Validiscan’s scanner groups findings by rule, selector and HTML shape, so the same viewport tag on every page of a theme becomes one finding.

How to fix it

Remove user-scalable=no and any maximum-scale value below 2 from the <meta name="viewport"> tag in the layout template; content="width=device-width, initial-scale=1" is enough.

WCAG success criteria

EN 301 549 clauses

The EN 301 549 clause of each criterion, by version of the standard
WCAG criterion Version 3.2.1 Version 4.1.1
1.4.4 9.1.4.4 9.1.4.4

Where a recipe fixes it

Shopify: recipe meta-viewport-zoom

Show the before and after (1)
Before and after Example data

layout/checkout.liquid Changes to layout/checkout.liquid: 1 added, 1 removed

Changes to layout/checkout.liquid: 1 added, 1 removed
Line before Line after Change Code
6 6 <html class="no-js">
7 7 <head>
8 8 <meta charset="utf-8">
9 Removed <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
9 Added <meta name="viewport" content="width=device-width,initial-scale=1">
10 10 <meta name="robots" content="noindex">
11 11 <link rel="canonical" href="{{ canonical_url }}">
12 12 <!-- Checkout assets: //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/ (served locally by the fixture server) -->

layout/theme.focused.liquid Changes to layout/theme.focused.liquid: 1 added, 1 removed

Changes to layout/theme.focused.liquid: 1 added, 1 removed
Line before Line after Change Code
10 10 <head>
11 11 <meta charset="utf-8">
12 12 <meta http-equiv="X-UA-Compatible" content="IE=edge">
13 Removed <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
13 Added <meta name="viewport" content="width=device-width,initial-scale=1">
14 14 <title></title>
15 15 <link rel="canonical" href="{{ canonical_url }}">
16 16 <!-- Theme assets: //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/ (served locally by the fixture server) -->

layout/theme.liquid Changes to layout/theme.liquid: 1 added, 1 removed

Changes to layout/theme.liquid: 1 added, 1 removed
Line before Line after Change Code
11 11 <head>
12 12 <meta charset="utf-8">
13 13 <meta http-equiv="X-UA-Compatible" content="IE=edge">
14 Removed <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
14 Added <meta name="viewport" content="width=device-width,initial-scale=1">
15 15 <meta name="theme-color" content="{{ settings.color_background }}">
16 16 <link rel="canonical" href="{{ canonical_url }}">
17 17 {%- comment -%} On the live store theme assets load from //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/; the fixture serves them from {{ routes.root_url }}assets/. {%- endcomment %}

Shopware: recipe meta-viewport-zoom

Show the before and after (1)
removes the zoom lock from the fixture theme and the rule stops firing Example data

Resources/views/storefront/layout/meta.html.twig Changes to Resources/views/storefront/layout/meta.html.twig: 1 added, 1 removed

Changes to Resources/views/storefront/layout/meta.html.twig: 1 added, 1 removed
Line before Line after Change Code
6 6
7 7 {% block layout_head_meta_tags_viewport %}
8 8 {# Added by the merchant's agency to stop "zoom jumps" on iOS. #}
9 Removed <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
9 Added <meta name="viewport" content="width=device-width, initial-scale=1">
10 10 {% endblock %}
11 11
12 12 {% block layout_head_meta_tags_general %}

WooCommerce: recipe meta-viewport-zoom

Show the before and after (1)
re-enables zoom in every header template of the fixture theme Example data

header-checkout.php Changes to header-checkout.php: 1 added, 1 removed

Changes to header-checkout.php: 1 added, 1 removed
Line before Line after Change Code
12 12 <head>
13 13 <meta charset="<?php bloginfo( 'charset' ); ?>">
14 14 <?php // VALIDISCAN-SEED meta-viewport: zooming is disabled. ?>
15 Removed <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
15 Added <meta name="viewport" content="width=device-width, initial-scale=1">
16 16 <?php wp_head(); ?>
17 17 </head>
18 18

header.php Changes to header.php: 1 added, 1 removed

Changes to header.php: 1 added, 1 removed
Line before Line after Change Code
14 14 <head>
15 15 <meta charset="<?php bloginfo( 'charset' ); ?>">
16 16 <?php // VALIDISCAN-SEED meta-viewport: zooming is disabled ("stops iOS zooming into inputs"). ?>
17 Removed <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
17 Added <meta name="viewport" content="width=device-width, initial-scale=1">
18 18 <?php wp_head(); ?>
19 19 </head>
20 20

Magento: recipe meta-viewport-zoom

Show the before and after (1)
removes the zoom block from default_head_blocks.xml and validates Example data

app/design/frontend/Validiscan/fixture/Magento_Theme/layout/default_head_blocks.xml Changes to app/design/frontend/Validiscan/fixture/Magento_Theme/layout/default_head_blocks.xml: 1 added, 1 removed

Changes to app/design/frontend/Validiscan/fixture/Magento_Theme/layout/default_head_blocks.xml: 1 added, 1 removed
Line before Line after Change Code
3 3 <head>
4 4 <!-- VALIDISCAN-SEEDED meta-viewport: pinch zoom disabled (Luma 2.0-2.3 default kept by the theme).
5 5 Fixed variant: content="width=device-width, initial-scale=1". -->
6 Removed <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
6 Added <meta name="viewport" content="width=device-width, initial-scale=1"/>
7 7 <meta name="format-detection" content="telephone=no"/>
8 8 <css src="css/styles-m.css"/>
9 9 <css src="css/styles-l.css" media="screen and (min-width: 768px)"/>

Start with a free check of your shop.

Send your shop’s address. Validiscan scans it and replies with every failure the scan can prove, with the page and the code.

Request a free check

Or write to info@validiscan.com.

What the free check covers, and what it leaves out
You send
your shop’s address
Pages scanned
up to 15
You get
every failure the scan can prove, with the page and the code
On your shop
public pages only; no login, nothing bought, no forms sent
What it is not
a full audit

Write to Validiscan

For a free check, give the address of your shop and its platform.

Validiscan uses what you send to answer you. Privacy notice