媒体查询在iPhone Safari上失效,90%以上是viewport元标签缺失、重复或位置错误所致;必须确保<meta name="viewport" content="width=device-width, initial-scale=1">唯一且位于<head>最顶部,否则浏览器默认以980px视口渲染,导致max-width媒体查询永不匹配。

媒体查询在iPhone Safari上失效,90%以上是viewport元标签缺失、重复或位置错误导致的。 它不是CSS写错了,而是浏览器压根没进入“移动适配模式”,还在用980px默认视口渲染页面。
viewport meta标签必须存在且唯一
iPhone Safari解析HTML时,一旦发现
里没有meta name="viewport",就会强制启用“桌面模拟视口”(layout viewport = 980px),此时@media (max-width: 768px)永远不匹配——因为视口宽度根本不是768,而是980。
- 检查HTML源码,确认
<meta name="viewport" content="width=device-width, initial-scale=1">出现在<head>最顶部,且只出现一次 - 不要用JS动态插入:
document.head.innerHTML += '...'或document.write()在Safari中大概率被忽略 - 避免服务端模板(如Next.js、Nuxt)因占位符或注释把viewport标签挤到
<head>靠后位置——它必须是<head>内第一个或第二个标签
别用max-device-width,改用max-width
max-device-width在iOS/iPadOS/macOS Safari中早已失效:系统返回的是逻辑像素而非物理屏幕宽度,且该媒体特性已被W3C弃用。你写的@media (max-device-width: 768px)在现代Safari里不会触发。
- 一律替换为
@media (max-width: 768px)——它基于当前视口宽度,可响应缩放、分屏、DevTools调整 - 注意:视口宽度受
initial-scale影响;若设了initial-scale=0.5,100vw就等于2倍设备宽度,断点值需同步调整 - 不要依赖
device-pixel-ratio做布局判断——它不可靠,也不响应式重算
CSS文件加载失败或语法错误会静默屏蔽后续媒体查询
媒体查询不是独立模块,它和普通CSS规则共享同一个解析上下文。前面一行CSS语法出错(比如@keyframes缺}、属性漏分号、括号不匹配),可能导致浏览器跳过之后所有规则,包括整个@media块。
立即学习“前端免费学习笔记(深入)”;
- 打开Safari开发者工具(macOS + iOS配对调试),在Console里看有没有
Parse error或Invalid CSS property name - 临时删掉所有非必要CSS,只留viewport meta + 一条最简媒体查询(如
@media (max-width: 768px) { body { background:red } }),确认是否生效 - Parcel等构建工具默认启用
cssnano压缩,可能误删未使用的媒体查询;检查.cssnanorc是否配置了discardUnused: false
iOS 15+ “请求桌面网站”会干扰vh单位,但不影响媒体查询本身
这个选项只改变vh、vw的计算基准(从视觉视口变为布局视口),@media (max-width: ...)仍按当前视口宽度判断,不受影响。如果你发现媒体查询和vh同时异常,优先排查viewport meta是否被覆盖或重复声明。
- 真机测试时,下拉地址栏确认是否启用了“请求桌面网站”——它会让
100vh变成980px高,但max-width媒体查询照常工作 - Safari 15.4之前不支持
clamp(1rem, 2vh, 1.5rem)这类含vh的表达式,但@supports检测和max-width查询完全正常 - 旧Edge中
@supports (prefers-reduced-motion: reduce)与逻辑属性组合可能失效,但这和iPhone Safari无关
真正容易被忽略的,是多层框架嵌套场景下的viewport透传问题:父页有正确viewport,iframe里的子页面依然需要自己声明——父页的设置对它完全无效。


















