是移动端页面正常渲染的必要开关,必须置于 最开头且含 width=device-width, initial-scale=1,禁用 user-scalable=no 等限制缩放属性,否则违反可访问性标准。

没写 <meta name="viewport">,移动端页面就是“半残”——文字小得看不见、布局横向溢出、媒体查询压根不触发。它不是可选项,而是浏览器渲染的开关。
viewport 必须放在 最开头,且不能动态插入
浏览器顺序解析 HTML,<meta name="viewport"> 必须在首次渲染前生效。一旦 layout viewport 按默认 980px 初始化完成,后续任何修改都无效。
- ✅ 正确位置:紧贴
<meta charset>后、<title></title>下方,内最靠前处 - ❌ 错误做法:写在
里;用 JS 执行document.head.appendChild();被 SSR 框架注释或占位符挤到后面 - ⚠️ 框架注意点:Next.js 要确认
next/head渲染后源码里真有该标签;Vue CLI 用vue-meta时需检查服务端吐出的 HTML 是否已含,不能只靠客户端补 - ? 调试方法:DevTools → Elements → 搜索
viewport;再执行document.querySelector('meta[name="viewport"]')?.content确认值未被覆盖或重复声明
width=device-width, initial-scale=1 必须配对,缺一不可
只写 width=device-width,iOS Safari 可能仍按 980px 渲染再缩小;只写 initial-scale=1,某些安卓 WebView 会无视设备宽度,导致横向滚动。二者共同作用,才能让 CSS 像素与设备物理像素对齐,媒体查询断点才准。
- ✅ 推荐最小可用配置:
<meta name="viewport" content="width=device-width, initial-scale=1"> - ❌ 危险写法:
width=375(折叠屏横屏崩)、width=1200(小屏强制拉伸)、initial-scale=1不带width=device-width - ⚠️ 注意:
device-width不是物理像素,而是经 DPR 换算后的 CSS viewport 宽度(如 iPhone 14 Pro 是 430px),硬写死数值毫无意义
别碰 user-scalable=no 和 maximum-scale=1
这三者连用:user-scalable=no, maximum-scale=1, minimum-scale=1,等于锁死所有缩放能力。iOS 13+ 会降权该页面,甚至弹提示“该网站可能无法正常工作”;更关键的是,它直接违反 WCAG 2.1 可访问性标准——视力障碍用户开系统「更大字体」或「辅助缩放」后,文字会被截断、按钮点不到。
- ✅ 合理替代:
touch-action: manipulation控制区域手势,或用 CSS 限制特定容器可缩放 - ❌ 高危组合:
user-scalable=no, maximum-scale=1, minimum-scale=1—— 业务页面请删掉 - ⚠️ 特殊例外极少:纯展示型 kiosk 屏、嵌入式 WebView(且 native 层已统一接管手势)
- ? 测试必须项:打开 iOS 「辅助功能 → 显示与文字大小 → 更大字体」,验证是否还能正常放大
写了 viewport 还是错乱?先查内容是否溢出视口
<meta name="viewport"> 只管“画布怎么铺开”,不解决布局、字体、图片的具体适配。常见翻车现场都出在这里:
- CSS 里写了
width: 100vw加上padding或border导致实际超宽 - 某个
<div> 写了固定 <code>width: 375px(在 iPhone 13 上没问题,在折叠屏横屏下直接偏左) - 图片没加
max-width: 100%; height: auto;,直接撑爆容器引发横向滚动 - 媒体查询用了
@media (max-width: 767px)却忘了在大屏样式里重置display或flex-direction,导致小屏规则残留覆盖
viewport 不解决图片模糊,srcset 才管用;也不影响 DPR 导致的 1px 边框发虚,那得靠 transform: scale(0.33) 或高倍图策略。它只决定 CSS 像素和设备物理像素的映射关系——这点最容易被当成万能胶,但其实只是起点。











