一张 JPEG 缩到十几像素,在 Chrome 里线条更粗,换到 Firefox 又正常。文件没变,CSS 尺寸也没变,像素却像换了一套画法。

一个常见解释是 Chrome 在 JPEG 解码时启用了缩放解码,也就是 partial IDCT scaling:不先完整解出原图,再缩成目标尺寸,而是在解码阶段少算一些数据。这个方向有技术依据,但目前还不能写成定论。

关键缺口很具体:原图多大、CSS 显示多大、设备像素比是多少,浏览器究竟请求了哪个解码尺寸。缺少这些信息,“15px 命中 1/8 缩放档”只是猜测。

JPEG 可以边解码边缩小,但 15px 说明不了什么

JPEG 会把图像分成 8×8 像素块,再把每个块转换成不同频率的信息。缩小图片时,解码器可以少处理一部分高频细节,直接输出较低分辨率的结果。

这样做有现实收益:少占内存,也少做计算。网页里若有大量图片,省下来的不是纸面参数,而是解码时间和滚动时的压力。

代价也很直接。细线、锐利边缘和小字依赖高频信息。它们一旦在解码阶段被简化,后续再怎么缩放,也补不回来。最终观感可能更粗、更软,甚至出现轻微明暗变化。

但显示成 15px,不等于解码器必然用了 1/8 档。只有原图尺寸、DPR 和浏览器请求的目标位图尺寸共同满足条件,这条路径才可能被触发。比如 CSS 写着 15px,在 DPR 为 2 的屏幕上,浏览器实际需要的可能是 30 个设备像素。

Chrome、Firefox 也不只是换了一个 JPEG 解码器。图像从文件走到屏幕,要经过多层处理:

环节可能造成的差异排查方法
JPEG 解码高频细节被提前舍弃对比原尺寸解码后再缩小的结果
缩放滤镜边缘变软、变粗或出现振铃改用整数比例,比较不同 CSS 尺寸
DPR 与页面缩放实际目标像素数变化固定系统缩放、页面缩放和 DPR
色彩管理灰度与颜色观感不同检查 ICC 配置,改用标准 sRGB
GPU 合成截图与实际显示存在差异关闭硬件加速做交叉测试

因此,把差异全部归给 partial IDCT scaling,证据还不够。它是嫌疑之一,不是已经落锤的原因。

真要定位,测试比猜源码更快

这类问题最容易被一句“浏览器渲染不同”含糊带过。开发者真正需要的是一组能排除变量的对照。

可以准备同一份图像内容,分别导出为 JPEG、PNG 和 SVG,再固定以下条件:

  • 记录原图像素尺寸、CSS 尺寸和 DPR。
  • 固定 Chrome、Firefox 的具体版本与操作系统。
  • 把页面缩放设为 100%,关闭 CSS transform。
  • 分别测试整数缩放和非整数缩放。
  • 用浏览器截图取样,不靠肉眼记忆比较。
  • 再关闭硬件加速复测一次。

判断结果也不复杂。

如果 JPEG 有差异,PNG 没有,问题更可能出在 JPEG 解码或色彩处理。若 JPEG、PNG 都变,缩放滤镜和合成路径的嫌疑更大。若差异只在某个 DPR 或非整数尺寸出现,先查目标像素取整,不要急着追解码器源码。

还可以做一组更直接的实验:先在图像工具中把 JPEG 缩到目标像素尺寸,再让浏览器按 1:1 显示。若浏览器差异消失,问题多半发生在浏览器的缩放链路;若差异仍在,则要继续检查颜色配置和解码输出。

没有这套对照,源码里的某个优化分支再像答案,也只能算线索。

小图标使用 JPEG,本身就是一笔不划算的交易

JPEG 在 1992 年成为标准时,主要解决的是照片压缩。照片里有连续色调,少掉一点高频信息通常不扎眼。图标、细线和文字恰好相反:面积很小,边缘却承担了大部分视觉信息。

这段历史并不复杂。工具没有失灵,只是被安排到了不擅长的位置。

素材更合适的格式原因
图标、Logo、线稿SVG任意尺寸仍保持清晰
必须逐像素控制的小图PNG无损,跨浏览器结果更稳定
照片、复杂渐变JPEG压缩效率高,细节损失通常可接受

如果你负责设计系统,最现实的动作是把 JPEG 从图标资产管线里清出去。能拿到矢量源文件就用 SVG;只能交付位图时,至少导出目标尺寸对应的 PNG,并覆盖常用 DPR。

如果你维护前端页面,也别用一张大 JPEG 包打天下,再把缩放结果交给各浏览器决定。它省的是几份资源管理工作,换来的却是跨平台验收、截图回归和设计争议。

我不太买账“Chrome 为性能抄近道,所以图片变粗”这种干脆叙事。浏览器当然会做性能取舍,但在缺少版本、尺寸和调用路径证据时,把优化直接判成元凶,只是用一个技术名词替代排查。

《论语》说,“工欲善其事,必先利其器。”放到这里还要再补半句:也得先选对器。JPEG 擅长压照片,不擅长守住十几个像素里的细线。浏览器差异只是把这笔旧账翻了出来。