viewport 必须写对,否则后续所有适配都失效;正确写法唯一:<meta name="viewport" content="width=device-width, initial-scale=1.0">,缺一不可,且须置于 <head> 最顶部。

viewport 必须写对,否则后续所有适配都失效
不加 <meta name="viewport">,移动端默认按 980px 渲染,文字小到无法阅读;写了但 content 错误,@media 规则压根不会触发。这不是兼容性问题,是渲染开关没打开。
正确写法只有一种核心组合:width=device-width, initial-scale=1.0,缺一不可:
-
width=device-width单独存在时,Android Chrome 某些版本会强制缩放,导致布局偏移 -
initial-scale=1.0单独存在时,iOS Safari 横屏可能忽略宽度声明,内容横向溢出 - 禁止加
user-scalable=no或maximum-scale=1.0:违反 WCAG 可访问性要求,iOS 13+ 已部分忽略,且对视障用户构成实际障碍 - 必须放在
<head>最顶部,不能等 JS 加载完再动态插入——浏览器解析 HTML 时就已锁定视口行为
媒体查询要用 min-width,别用 max-width 做断点
写 @media (min-width: 768px) 是“渐进增强”,写 @media (max-width: 767px) 是“条件删除”。后者容易引发样式覆盖混乱、调试困难、构建产物体积膨胀。
移动优先不是口号,是结构逻辑:
立即学习“前端免费学习笔记(深入)”;
- 基础样式(如卡片宽度
width: 100%、文字大小font-size: 1rem)直接写在常规 CSS 中 - 仅在大屏需要时,用
min-width“加”规则:@media (min-width: 768px) { .card { width: 48%; } } - 断点值按内容定,不是设备型号:比如容器撑到 750px 才需双列,那就用
min-width: 750px,而非硬套 768px - 避免混用
min-width和max-width:同一组件上同时存在两者,极易因层叠顺序错乱导致样式失效
结构语义化 + data-属性标记,比 UA 判断更可靠
直接解析 navigator.userAgent 在微信、飞书、钉钉等容器里几乎必然误判——它们的 UA 字符串高度混杂,且常被客户端主动伪造。
真正可控的做法是让宿主环境注入平台特征:
- 客户端初始化时往
<html>写入data-platform="wechat"、data-os="ios"、data-webview="true" - CSS 中用属性选择器精准控制:
[data-platform="wechat"] .btn { padding: 12px 24px; } - 若必须运行时探测,优先查
navigator.standalone(iOS PWA)、window.webkit(Safari),而不是正则匹配 UA - 绝对避免在关键路径中多次读取 UA——每次调用都触发重排或阻塞渲染
flex-wrap 在 Android 4.4 WebView 中是稳定 Bug,不是偶发
Android 4.4 及更早 WebView 对 flex-wrap: wrap、flex-basis、gap 的支持不是“偶尔不生效”,而是稳定不工作。用 'flexWrap' in document.documentElement.style 检测完全不可靠——该属性始终返回 true,但实际渲染失败。
真实可行的兜底方案只有两个:
- 简单布局:改用
display: inline-block+vertical-align: top+ 百分比宽度,兼容性覆盖到 Android 4.0+ - 卡片流类复杂布局:用 JS 控制列数(如根据
window.innerWidth判断每行渲染 1 个或 2 个),比依赖 CSS 行为更可控 - 别尝试用 Grid 降级 fallback——该环境 Grid 基本不可用,且 fallback 逻辑本身就会引入新 bug
- 如果业务必须支持 Android 4.4,建议直接放弃 flex-wrap,把布局逻辑收归 JS 控制
最常被跳过的其实是 sizes 属性和 min-width 媒体查询方向——它们不显眼,但一旦漏掉,适配就在用户看不见的地方悄悄崩了。



















