应该使用的标签
在每个页面的 <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 的取值
| 值 | 示例 | 作用 |
|---|---|---|
width | width=device-width | 布局宽度。device-width 是以 CSS 像素计的屏幕宽度;也可以写数字,但很少是好主意。 |
initial-scale | initial-scale=1 | 页面打开时的缩放级别。 |
minimum-scale / maximum-scale | maximum-scale=5 | 缩放的限制。较低的最大值会阻止缩放,所以不要写 maximum-scale。 |
user-scalable | user-scalable=yes | 是否允许双指缩放。不要写它。 |
viewport-fit | viewport-fit=cover | 让页面延伸到刘海或圆角下方,需要搭配 env(safe-area-inset-*) 内边距。 |
interactive-widget | interactive-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 标签会影响桌面浏览器吗?
不会。桌面浏览器会忽略它;在那里,布局宽度就是窗口宽度。这个标签只对手机和平板起作用。