移动端页面缩成一团、文字小、点击错位,90%因viewport未写或写错;必须在中硬编码,禁用user-scalable=no等限制缩放属性,避免js动态插入或固定width值。

移动端页面在手机上缩成一团、文字小得看不清、点击区域错位——90% 以上是 <meta name="viewport"> 没写对或根本没写。它不是“锦上添花”,而是浏览器渲染的启动开关,缺了就直接走默认 980px 模式。
viewport meta 标签必须写全且放对位置
只写 width=device-width 不够,必须搭配 initial-scale=1.0;否则 iOS Safari 会先按 980px 渲染再缩放,导致 touch 坐标偏移、字体模糊、CSS 媒体查询断点失效。
- 正确写法(最小可用组合):
<meta name="viewport" content="width=device-width, initial-scale=1.0"> -
user-scalable=no、maximum-scale=1.0等禁缩放参数要慎用:iOS 13+ 会降权提示,WCAG 可访问性不达标,横屏时也可能卡死 - 该标签必须硬编码在 HTML 的
里,不能靠 JS 动态插入,也不能依赖 SSR 框架在客户端补 —— iOS Safari 和部分 Android WebView 在首次渲染后就忽略它 - 别写
width=375或width=414这类固定值:不同设备的 “375” 含义不同(DPR、系统缩放、横竖屏),且横屏时直接崩
rem 基准必须前置计算,不能等 DOM 加载完再设
用 document.documentElement.style.fontSize 在 DOMContentLoaded 里设 rem,会导致闪屏:浏览器先按默认 16px 渲染一次,再重绘。用户肉眼可见文字突然变大/变小。
- 可靠做法是把计算逻辑塞进
的内联<style></style>中,用calc()直接算出根字号:html { font-size: calc(100vw / 375 * 16px); }(假设设计稿宽 375px) - Safari 旧版本(≤ iOS 12)不支持
calc()混用单位(如100vw / 375 * 1rem),必须统一为px或纯数字 - 避免 JS 读取
window.innerWidth再 setStyle:横竖屏切换、双击放大后,该值可能滞后或不准,尤其在 iOS 上
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 之前也有类似兼容性问题,表现不一致 - 如果用了
flex-direction: column+height: 100vh,记得父级也设height: 100%,否则 iOS 8–9 里子项高度算成 0
srcset 和 lazyload 冲突时,优先关第三方库
写了 <img srcset="a.jpg 320w, b.jpg 768w" sizes="(max-width: 320px) 100vw, 50vw">,但 Network 面板里永远只加载 a.jpg —— 大概率是第三方 lazyload 库(比如 lozad.js)直接改了 src,而忽略了 srcset 的多图选择逻辑。
- 原生
loading="lazy"是安全的,浏览器自己处理srcset选图,无需额外干预 - 慎用第三方 lazyload:很多库会劫持
src属性,破坏响应式图片机制 - 如果必须用第三方库,确认它是否支持
data-srcset+ 手动触发逻辑,而不是粗暴覆盖src
真正难的不是写多少代码,而是哪些地方不能“想当然”:viewport 必须在首帧前生效、rem 基准不能靠 JS 补、老 iOS 的 flex 行为和现代文档写的不一样、lazyload 和 srcset 天然互斥——这些点一旦漏掉,调试时就会陷入“明明写了却不起作用”的循环。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











