viewport标签必须放在<head>最顶部且内容为width=device-width、initial-scale=1.0,否则图片响应式失效;常见错误包括动态插入、重复声明、写成width=375或添加user-scalable=no。

viewport 标签没写对,图片再怎么设都白搭
手机上图片撑破屏幕、页面能左右拖动、文字糊成一团——八成是 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 没生效。它必须放在 <head> 最顶部,不能动态插入,不能重复写,更不能写成 width=375 或加 user-scalable=no。
常见失效场景:
- Vue/React SSR 渲染漏掉这行,真机加载时浏览器已按 980px 宽度解析完 DOM
- 写了
maximum-scale=1.0,iOS Safari 双击放大直接失灵,读屏用户也被锁死 - 在
<body>里补写,浏览器早跳过解析阶段了
验证方式:Chrome DevTools 切手机模式 → 右键“查看网页源代码”,确认这行在 <head> 开头附近。
img { max-width: 100%; height: auto; } 为什么经常不生效
这行 CSS 只解决“不溢出容器”,但前提是父容器有明确宽度参照。浏览器计算 max-width: 100% 时,会逐级向上找第一个有明确宽度的祖先元素。
立即学习“前端免费学习笔记(深入)”;
典型失效原因:
- 父容器只写了
display: flex却没设width或max-width,图片“找不到 100% 是多少” - Flex 容器里的
<img>默认带min-width: auto,死守原始尺寸,max-width: 100%被无视 -
<img src="x.jpg" width="800" height="600">这类内联属性会覆盖height: auto,高度被锁死 - 某些框架(如 Bootstrap)全局设了
img { max-width: 100% },你又加了style="width: 500px",导致冲突
修复办法:给图片加 min-width: 0,同时确保其父 Flex/Grid 子项也设 min-width: 0 —— 不是加在图片上就完事,得双管齐下。
srcset + sizes 才是真正省流量的关键
max-width: 100% 只控制显示,不减少下载体积。小屏加载 2MB 桌面图再缩到 375px,像素全下了,带宽白耗,首屏卡顿。
正确做法是让浏览器自己选图:
-
srcset提供多尺寸图源,用w描述符(如image-480w.jpg 480w),别混用480w和2x,否则整条srcset被忽略 -
sizes是字符串,不是 CSS,不支持calc(),但支持媒体查询语法:sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw" -
sizes必须和真实 CSS 布局断点一致,比如布局用768px,就别写成767px;如果图片在栅格中占 1/3 宽,sizes就该是"(max-width: 768px) 100vw, 33.33vw",不是硬写100vw
示例:
<img src="default.jpg"
srcset="img-480w.jpg 480w,
img-800w.jpg 800w,
img-1200w.jpg 1200w"
sizes="(max-width: 480px) 100vw,
(max-width: 768px) 50vw,
33vw"
alt="响应式图片">
什么情况下必须用 <picture>
当不同屏幕需要完全不同的构图或格式时,<picture> 不是可选项,是刚需。
适用场景:
- 手机裁切人脸、桌面展示全景 Banner:
<source media="(max-width: 480px)" srcset="face-crop.jpg"> - 强制用 WebP 或 AVIF 并提供降级:
<source type="image/webp" srcset="img.webp">后必须跟<img src="img.jpg" alt=""> -
<source>的media属性断点必须和真实 CSS 布局断点一致 -
<picture>必须包裹在<img>外层,顺序错(比如<img>在前)就完全失效
注意:object-fit 在父容器没设明确宽高时根本不生效;旧版 Edge 解析 sizes 时,媒体查询里有空格(如 (max-width: 768px))会导致整条属性失效。



















