只负责选图,不控制渲染形态;真正解决比例失调的是object-fit(如cover填满裁剪、contain完整显示留白)及容器显式宽高约束。

picture 本身不解决比例失调,object-fit 才管这个
<picture></picture> 只负责选图,不控制渲染形态。它可能给你加载了一张 16:9 的图,但容器是 1:1,结果图片被拉伸或留白——这不是 <picture></picture> 的问题,是 CSS 渲染没跟上。
真正起作用的是 object-fit 和容器约束:
-
object-fit: cover:等比缩放填满容器,溢出裁剪(最常用,类似背景图background-size: cover) -
object-fit: contain:等比缩放,完整显示,留白不可避免 -
object-fit: fill:直接拉伸填满(就是默认行为,慎用) - 必须配合显式宽高:比如父容器设
width: 300px; height: 200px;,否则object-fit无参照
为什么 <source></source> 切图后还是变形?检查 media 断点是否互斥
常见现象:小屏加载了 mobile-crop.jpg,大屏加载 desktop-wide.jpg,但两者宽高比不同,而容器尺寸固定,导致一个被裁、一个留白——你以为是比例问题,其实是艺术指导没对齐。
关键点不在图片本身,而在断点逻辑是否让每种设备只命中一张图:
- ❌ 错误写法:
media="(max-width: 768px)"和media="(min-width: 768px)"重叠,768px 设备可能随机选其一 - ✅ 推荐写法:
media="(max-width: 479px)"→media="(min-width: 480px) and (max-width: 1023px)"→media="(min-width: 1024px)" - 断点之间不留缝隙也不重叠,确保每个视口宽度只匹配一个
<source></source>
<img> 的 src 必须存在且尺寸一致,否则 fallback 会触发 layout shift
当所有 <source></source> 都没匹配上时,浏览器静默回退到 <img src>。如果这张兜底图的原始尺寸和前面任一 <source></source> 图不一致(比如 WebP 是 1200×800,JPEG 是 1198×799),浏览器会重排布局,页面“闪一下”——这就是比例失调的视觉错觉。
实操要点:
- 所有格式的图(WebP/JPEG/AVIF)必须保持完全相同的固有宽高像素值
- 用
identify -format "%wx%h" image.webp(ImageMagick)批量校验尺寸 - 不要依赖“看起来差不多”,差 1px 就可能触发 layout shift
-
<img>的src不可省略,也不可为空字符串;否则整个<picture></picture>渲染为空白
用 sizes + srcset 替代 media 时,别漏掉 sizes 值
当只换分辨率(如 1x/2x)、不换构图时,<source srcset="a.jpg 1x, a@2x.jpg 2x" sizes="100vw"></source> 比 media 更轻量。但漏掉 sizes 会导致浏览器无法估算所需像素宽度,直接退化为加载第一个 srcset 项——你写了 2x 图,结果所有设备都下 1x。
注意:
-
sizes必须是合法 CSS 长度表达式,比如sizes="(max-width: 600px) 100vw, 50vw" - 不能写成
sizes="100%"或sizes="100vw"(缺少媒体条件时需加括号) - 如果用了
w描述符(如photo-400w.jpg 400w),sizes就更不能少,否则浏览器无法做匹配
最容易被忽略的是:所有配置项(media 括号、sizes 语法、type 与响应头一致性)只要错一个字符,<picture></picture> 就静默失效,你根本看不到报错,只看到模糊图或白边——验证时别只看 Network 面板文件名,要开新页查实际像素尺寸和 Content-Length。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











