Menu

meta viewport 标签:width=device-width 详解

viewport meta 标签告诉手机按屏幕宽度而不是桌面宽度来排版页面。了解标准写法、每个值的作用、响应式 CSS 为什么依赖它,以及应该避免哪些值。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

应该使用的标签

在每个页面的 <head> 中加上这一行:

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

width=device-width 让布局与屏幕一样宽,initial-scale=1 让页面以 100% 的缩放比例打开。大多数网站只需要这些。下面是一个加上了这个标签的完整页面:

脚本读取了这个标签和布局宽度。桌面浏览器会忽略 viewport 标签,所以在这个预览中,宽度就是预览框的宽度。在手机上,因为有这个标签,同一个文件报告的是手机的宽度(通常为 360 至 430 个 CSS 像素)。

没有它时手机会怎样

找不到 viewport 标签的移动浏览器会认为页面是为电脑设计的。它会按大约 980 像素的宽度排版页面,再把整个页面缩小以适应屏幕。下面两部模拟手机加载的是同一个页面,一个按 980px 排版,一个按手机宽度排版,两者都缩放到相同的大小:

在第一部手机上,16px 的文字变得很小,读者不得不用双指缩放。在第二部手机上,文字依然清晰,而且因为 @media (max-width: 600px) 规则生效,各列会上下堆叠。这就是这个标签的第二个作用:媒体查询看到的是布局宽度,所以没有这个标签,手机报告的是 980px,你的移动端样式永远不会生效。把 show('with', 375) 中的 375 改成 980,两部手机看起来就一样了。

标签只完成了一半的工作

viewport 标签给了你一个窄布局;你的 CSS 必须能放得进去。只要有一个元素的固定宽度超过屏幕,整个页面就会横向滚动:

第一个盒子可以横向滚动;第二个会缩小以适应。给图片和其他宽元素设置 max-width: 100%,并且优先使用弹性宽度(百分比、fr、flexbox),而不是固定的像素宽度。

viewport 的取值

值示例作用
widthwidth=device-width布局宽度。device-width 是以 CSS 像素计的屏幕宽度;也可以写数字,但很少是好主意。
initial-scaleinitial-scale=1页面打开时的缩放级别。
minimum-scale / maximum-scalemaximum-scale=5缩放的限制。较低的最大值会阻止缩放,所以不要写 maximum-scale。
user-scalableuser-scalable=yes是否允许双指缩放。不要写它。
viewport-fitviewport-fit=cover让页面延伸到刘海或圆角下方,需要搭配 env(safe-area-inset-*) 内边距。
interactive-widgetinteractive-widget=resizes-content屏幕键盘如何影响布局。Android 上的 Chrome 支持。

各个值用逗号分隔。在有刘海的手机上铺满整个屏幕的页面是这样写的:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<style>
  body {
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
  }
</style>

不要禁止缩放

你会在一些旧模板中看到这个标签:

<!-- Avoid: stops people from zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

它会阻止双指缩放,而视力不佳的人依赖缩放,Lighthouse 等无障碍检查工具也会标记它。iOS 上的 Safari 会忽略 user-scalable=no,所以这个标签甚至无法稳定生效。如果在 iPhone 上点击表单字段时页面会放大,原因是输入框的字号小于 16px;请把输入框的 font-size 设为至少 16px,而不是禁用缩放。

常见错误

  • 忘了加这个标签。 没有它,响应式样式表在手机上毫无作用,因为媒体查询看到的是 980px 的布局。在页面模板中把它放在 title 标签旁边。
  • 值之间用分号分隔。 请用逗号:width=device-width, initial-scale=1。
  • 把宽度写死,比如 width=375。屏幕尺寸各不相同;请使用 device-width。
  • 用 user-scalable=no 或 maximum-scale=1 禁用缩放。
  • 把横向滚动归咎于这个标签。 找出比屏幕更宽的那个元素,给它设置弹性宽度。

常见问题

meta viewport 标签有什么作用?

它告诉移动浏览器布局应该有多宽。没有它,大多数手机会按大约 980 个 CSS 像素来排版页面,再缩小以适应屏幕。有了 width=device-width,布局宽度就与屏幕宽度一致,文字清晰可读,媒体查询也能生效。

标准的 meta viewport 标签怎么写?

<meta name="viewport" content="width=device-width, initial-scale=1">,放在 <head> 中。几乎所有响应式页面都应该这样写。

为什么我的 meta viewport 不起作用?

检查标签是否在 <head> 中、name 是否为 viewport、各个值是否用逗号分隔。如果页面仍然可以横向滚动,说明某个元素比屏幕更宽,比如固定宽度、大图片或很长的单词;这个标签无法修复比设备更宽的 CSS。

应该使用 user-scalable=no 或 maximum-scale=1 吗?

不应该。两者都会阻止用户缩放,而很多视力不佳的用户依赖缩放,它们也无法通过无障碍审查。何况 iOS 上的 Safari 本来就会忽略 user-scalable=no。

meta viewport 标签会影响桌面浏览器吗?

不会。桌面浏览器会忽略它;在那里,布局宽度就是窗口宽度。这个标签只对手机和平板起作用。

Coddy 编程语言插图

和 Coddy 一起学编程

开始