朋友的相册页被几十张原图拖到转圈:我给图片分了三档、用 srcset 让手机自己挑

朋友旅行回来,拍了上千张照片,让我帮忙做一个简单的相册页,准备发亲戚群里看。他把照片挑出来打包给我,我图省事,网页里直接 <img src> 指向每一张原图,配上瀑布流就发了。结果当晚他很尴尬地转述:有人说“你这页是不是坏了,半天不出来”,有人说“一打开手机流量就告警,赶紧退了”;等我把图换成小缩略图想救场,又有人抱怨“点进去想看清脸,放大全是糊的”。

折腾了一晚上,问题不是相册程序、也不是图床慢,而是我从头到尾只给了一个尺寸的图:要么全原图撑死流量,要么全缩略图糊成一片。把这页修好以后,我把“相册页到底该给多大的图”这件事按踩坑顺序记下来,下次再做带图页面不用重新趟一遍。

一、翻车现场:一屏照片,浏览器其实拉了几十兆

我先在电脑上打开觉得挺正常,照片“唰唰”就出来了。直到在手机蜂窝网络下复现,才发现真相:相册墙一屏几十张图,我每张都指向原图,每张原图好几兆,整页等于一次拉了几十兆。浏览器并不会因为图被显示成小卡片就少下载——它把整张大图拉到本地,再缩成小尺寸。

也就是说,用户看到的是小图,付出的却是原图的流量。手机性能弱一点、网络差一点,页面就一直在转圈;有的人甚至没等图出来就关掉了。

二、改成小图之后,又栽在“点进去看大图”

我当时的第一反应很简单:把图全部换成小尺寸不就好了?换完确实秒开,可新问题立刻来了——相册页是让人“看照片”的,点开任意一张想放大看,结果大图是用那张 300px 的小图强行拉大的,人脸、文字全糊。

这一下我才明白:列表小图和详情大图,本来就该是两个文件,不能用同一张图包打天下。 列表要的是“小而快”,详情要的是“大而清”,需求是相反的。

三、一张图该准备几档:原图、压缩图、缩略图

后来我固定按三档来备图,再没有在这两个极端之间反复横跳:

  • 原图:像素和信息完整、体积最大,只给“查看高清”“下载原图”这种入口,不在列表里直接铺;
  • 视觉无损压缩图:清理冗余元数据、优化编码,肉眼几乎看不出差,体积小一截,用来做详情页的大图;
  • 多级缩略图:固定宽度的小版本,像 100、200、300、600 这几档,宽度够显示就行,专门给相册墙、卡片、头像用。

相册墙用最接近显示尺寸的缩略图,点进去详情用压缩图,需要保存、打印的再给原图,各走各的路,就不会互相拖累。

四、为什么手机上连“小图”都会糊:DPR

在电脑上看,缩略图明明挺清晰,为什么换到手机上还是发虚?这是设备像素比(DPR)在起作用。

网页里写的宽度是逻辑像素,而高分屏(Retina 一类)的物理像素更密。手机上在浏览器里打印 window.devicePixelRatio,大多数是 2,少数是 3。一个 CSS 上 300px 宽的卡片,在 2 倍屏上实际要 600 个物理像素才够锐利;只给 300 的图,被拉到 600 就糊。

所以缩略图不能只按显示宽度备,得按“显示宽度 × DPR”,通常 1x、2x 两档就够;只有详情页主图这种需要放大看的才考虑 3x。档位也别堆太狠,3x 图体积上得快,不分场景全上 3x,反而把刚省下来的流量又吃回去了。

五、让浏览器自己挑:x 给头像,w 给瀑布流

备好了多档图,怎么让浏览器按设备自动选?我给相册页加了 srcset。它有两种写法,一开始我混着用踩了坑,分清楚就很简单。

固定尺寸的(头像、图标)用 x 描述符,按 DPR 选:

<img src="avatar-300.jpg"
     srcset="avatar-300.jpg 1x, avatar-600.jpg 2x"
     width="120" height="120" alt="头像">

宽度会变的(瀑布流、正文配图)用 w 描述符加 sizes,把每张图的固有宽度和“这张图在页面里占多宽”都告诉浏览器:

<img
  src="photo-600.jpg"
  srcset="photo-200.jpg 200w, photo-300.jpg 300w, photo-600.jpg 600w, photo-1400.jpg 1400w"
  sizes="(max-width: 600px) 100vw, (max-width: 1000px) 50vw, 320px"
  alt="旅行照片">

浏览器会结合容器宽度、DPR、网络状况自己挑一张,src 只负责给不支持 srcset 的浏览器兜底。

两条硬规矩我专门记牢:一是 w 和 x 不能写进同一个 srcset;二是用了 w 就一定要写 sizes,不写的话浏览器默认按整屏宽度算,多半会选偏大的图,省了等于没省。至于“窄屏换一种裁剪构图”,那是 <picture> + media 的艺术指导,跟分辨率分档不是一回事,别搅在一起。

六、我让朋友以后就这么传图

修好之后,我把相册页的流程也给他固定下来,免得下次又把原图一股脑塞进来:

  1. 每张成品都备好原图、一档视觉无损压缩图、几档固定宽度缩略图;
  2. 相册墙、卡片只放缩略图,详情页放压缩图,“下载/高清”单独给原图;
  3. 页面用 x 或 w + sizes 写好,让浏览器自己选;
  4. 要替换某张照片(比如换掉一张拍糊的),就用同名文件覆盖,链接不变,页面里的引用不用挨个改。

这一步并不绑死某一家:自己在对象存储上套一层图片处理,按尺寸实时生成各档,也能做到。我为了省事,朋友这些图统一放在图床小镇,上传后直接给原图、无损压缩和 100/200/300/600 几档缩略图的地址,URL、Markdown 都能直接复制,重传同名文件覆盖时链接也不变,不用我自己维护图片处理;但这纯属个人习惯,换成任何能输出多版本、外链稳定的图床或对象存储,做法和结果都一样。

“同名覆盖、链接不变”这件事我之前专门踩过:客户说文档里的截图还是旧的,我重传了三遍才发现自己一直在“新增”而不是“覆盖”,过程记在《客户说文档里的截图还是旧的,我重传了三遍才发现:我一直在“新增”而不是“覆盖”》里。另外相册页的图如果要嵌到别的网页、或者顺手发邮件,记得留意图源那边的防盗链白名单,否则页面里能看、换个地方就裂,这点我在《配了防盗链想防别人盗图,结果先把自己的订阅者全挡了:一晚 Referer 折腾记》里也验证过。

七、怎么确认它真的变快了

改完我没凭感觉收工,而是实打实验证了一遍:

  • 手机和电脑各打开一次,相册墙秒出、点开详情依旧清晰;
  • DevTools 的 Network 里看实际下载的是哪一档、整页拉了多少,切设备模拟不同 DPR,看选中的尺寸会不会变;
  • 控制台打印图片的 currentSrc,能直接看到浏览器最终挑了哪个文件;
  • 用 Network 节流模拟弱网,再看相册墙是不是仍然先出小图;
  • 无痕窗口打开一次,避免本地缓存造成“已经很快”的错觉。

写在最后

回过头看,相册页翻车和救场,本质上都是一句话:显示多大就给多大,再按手机的 DPR 多备一档,原图只留给真正需要高清的地方。 把“列表小图、详情中图、高清原图”分清楚,再用 srcset 把选择权交给浏览器,秒开和清晰就不必二选一了。

官网:https://imgbed.cn

posted @ 2026-10-27 21:16  234123412341234  阅读(15)  评论(0)    收藏  举报