viewport meta 标签告诉移动端浏览器,页面的布局区域要多宽、初始缩放比例是多少。几乎每个网站都应该在 <head> 中原样使用这一行:
<meta name="viewport" content="width=device-width, initial-scale=1">
没有它,手机会认为页面是桌面端设计,按大约 980 px 的宽度布局,再缩小到适合屏幕。你的响应式 CSS 根本没有机会生效。
没有 viewport meta 标签会怎样
最早的智能手机出现时,大多数网站都是为桌面屏幕设计的。为了能显示这些网站,移动端浏览器假装自己有一个桌面尺寸的“布局视口”(iOS Safari 和安卓 Chrome 中为 980 px),然后缩小页面,让整页都能放进屏幕。用户再用双指放大来阅读。
对于任何没有 viewport 标签的页面,这个默认行为至今仍然有效。在屏幕宽 390 px 的手机上,这样的页面会:
- 向 CSS 和 JavaScript 报告约 980 px 的视口宽度
- 永远不会匹配
(max-width: 600px)这样的媒体查询 - 文字只显示为预期大小的 40% 左右
如果你的网站在手机上看起来像一个缩小的桌面页面,首先检查这个标签。这是网站在手机上显示错乱的原因中最常见的一种。
每个取值的含义
| 取值 | 含义 | 是否推荐 |
|---|---|---|
width=device-width |
把布局视口设为设备的 CSS 像素宽度(例如很多 iPhone 为 390) | 推荐 |
initial-scale=1 |
初始缩放为 100%,1 个 CSS 像素对应 1 个设备无关像素 | 推荐 |
minimum-scale |
允许的最小缩放 | 很少需要 |
maximum-scale |
允许的最大缩放 | 避免小于 5 的值 |
user-scalable=no |
禁用双指缩放 | 避免 |
width=1024(固定数值) |
强制使用固定的布局宽度 | 响应式网站应避免 |
viewport-fit=cover |
让页面延伸到刘海和圆角下方 | 仅在配合安全区域内边距时使用 |
interactive-widget |
控制屏幕键盘如何调整页面大小 | 可选 |
为什么不应该禁用缩放
user-scalable=no 和 maximum-scale=1 会阻止用户放大页面。这会让低视力用户难以甚至无法阅读,也违反了 WCAG 关于文字可放大到 200% 的要求。Lighthouse 的无障碍审核会标记这个问题。
开发者加这些值,常常是为了阻止 iOS Safari 在表单字段上自动放大。正确的做法是让输入框的字号至少为 16 px:
input, select, textarea { font-size: 1rem; }
而且,较新的 iOS Safari 在双指缩放上本来就会忽略 user-scalable=no,所以这个标签主要是在其他浏览器上造成危害。
viewport-fit=cover 与安全区域
在有刘海、灵动岛或圆角的手机上,浏览器默认把页面限制在一个安全的矩形内。viewport-fit=cover 让页面占满整个屏幕,全出血设计可能需要这样做。这时你必须自己让内容避开刘海和主屏幕指示条:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
.site-header {
padding-left: max(1rem, env(safe-area-inset-left));
padding-right: max(1rem, env(safe-area-inset-right));
}
.bottom-bar { padding-bottom: env(safe-area-inset-bottom); }
请在横屏下测试,此时刘海位于侧边。
interactive-widget 与屏幕键盘
键盘弹出时,浏览器要么只缩小视觉视口(Chrome 和 Safari 的默认行为),要么调整整个布局的大小。较新的 interactive-widget 取值可以让你选择:
resizes-visual:默认值;布局大小不变,键盘遮住其中一部分resizes-content:布局视口缩小,因此使用100dvh的元素和固定页脚会移到键盘上方overlays-content:不调整任何大小;需要你用 VirtualKeyboard API 自行处理
各浏览器的支持情况不同(基于 Chromium 的浏览器支持;依赖它之前请先确认当前的支持情况),所以无论如何都要在真机上测试表单。
可以删除的过时取值
shrink-to-fit=no是针对 iOS 9 的权宜之计,现在已经没有作用。target-densitydpi是旧版安卓的取值,现已被忽略。<meta name="HandheldFriendly">和<meta name="MobileOptimized">是功能机时代的产物。
如何检查你的 viewport 标签
- 查看页面源代码,搜索
name="viewport"。应该恰好有一个。 - 在移动模式下运行 Lighthouse 审核(操作方法),它会报告缺失或阻止缩放的 viewport 标签。
- 用手机视图打开页面。在 DevTools 设备模式中,或在按真实手机尺寸加载页面的 Mobile View Extension 中,没有该标签的页面看起来是缩小的,文字很小。
常见问题
正确的 viewport meta 标签是什么?
<meta name="viewport" content="width=device-width, initial-scale=1">。只有在做全屏布局并处理安全区域时,才添加 viewport-fit=cover。
做响应式设计需要 viewport meta 标签吗?
需要。没有它,移动端浏览器会按大约 980 px 的宽度布局页面,移动端媒体查询永远不会生效。
使用 user-scalable=no 不好吗?
从无障碍角度看不好。它会阻止用户放大文字。表单字段上不想要的自动放大,请改用 16 px 的输入框字号来解决。