移动端适配需 viewport + 基准单位 + 布局逻辑协同:viewport 必须写 width=device-width, initial-scale=1.0;rem 根字号应在 head 内联 calc() 设置;老 ios flex 忽略 min-width,需加 flex-shrink: 0;srcset 失效多因第三方 lazyload 干扰。

移动端适配不是“选一个方案就行”,而是 viewport + 基准单位 + 布局逻辑 三者必须协同,漏掉任一环都会在 iPhone 或安卓高 DPR 屏上出问题。
viewport meta 标签必须写对,且不能少 initial-scale=1.0
只写 <meta name="viewport" content="width=device-width"> 是无效的。iOS Safari 会默认以 980px 宽度渲染再缩放,导致文字模糊、touch 事件坐标偏移、滚动卡顿。
- 正确写法只有这一种基础组合:
<meta name="viewport" content="width=device-width, initial-scale=1.0"> -
user-scalable=no和maximum-scale=1.0不要滥用:前者破坏双击放大可访问性,后者在部分安卓浏览器中禁用 pinch-zoom,WCAG 不合规 - 硬编码
width=375或width=320是典型错误——横屏时直接崩,且不同设备的“375”逻辑宽度不一致
rem 基准必须在 HTML 解析阶段就定死,不能等 JS 执行
用 document.documentElement.style.fontSize 在 DOMContentLoaded 里设 rem,会导致闪屏:先按浏览器默认 16px 渲染,再重绘。用户肉眼可见文字突然变大/变小。
- 推荐做法:在
内联一段<style></style>,用calc()直接算出根字号,例如:html { font-size: calc(100vw / 375 * 16px); } - Safari 旧版本(iOS 12 及更早)不支持
calc(100vw / 375 * 1rem)这种混用单位写法,必须统一为px - 如果用 JS 动态计算,需监听
resize和orientationchange,但要注意:横竖屏切换后clientWidth可能滞后,建议加防抖
flex 布局在老 iOS 上会吃掉 min-width,别信文档
在 iOS 12 及更早系统中,flex: 1 容器里的子元素即使写了 min-width: 200px,也会被压缩到 0 宽——这不是 bug,是 flex 算法老版本对 min-width 的忽略。
- 绕过方式:给该子元素加
flex-shrink: 0,强制不收缩 - 或改用
width: max-content; flex: 0 0 auto,比min-width更受老 iOS 尊重 - 别依赖
flex-basis控制关键尺寸:Android Chrome 80 之前也有类似兼容性问题
srcset 和 sizes 失效?先关掉第三方 lazyload
写了 <img srcset="a.jpg 320w, b.jpg 768w" sizes="(max-width: 320px) 100vw, 50vw"> 却只加载 a.jpg,大概率是用了 lozad.js 这类第三方 lazyload 库——它直接改 src,完全忽略 srcset 逻辑。
- 原生
loading="lazy"是安全的,浏览器自己处理srcset选择,且兼容性好(Chrome 76+、Safari 15.4+、Firefox 75+) - 若必须用第三方库,请确认它是否支持
data-srcset+ 手动解析逻辑,否则不如不用 - 另外注意:100vw 包含竖向滚动条宽度,iOS Safari 下有时多出几像素溢出,可用
max-width: 100vw; overflow-x: hidden抑制
真正难的不是写代码,而是理解「device-width 是逻辑像素」和「CSS px 在高 DPR 屏上不等于物理像素」这两点。很多问题其实都源于把设计稿的 750px 直接当成了物理宽度去算,结果在 iPhone 14 Pro 的 3x 屏上,2px 圆角根本看不见。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











