Skip to main content

Img

bbbottle

图片是 BBKi.ng 的主要内容之一,友好地展示图片是必须考虑的问题。

先写下第一行代码:

<img src="my-awesome-picture.jpg" />

这样就完成了图片展示。但是这种极简的做法存在一些问题,还谈不上友好。比如:

  1. 布局偏移问题。我们没有为 img 标签设定尺寸,导致图片加载期间,浏览器没有在文档中为其分配正确的空间。加载完成后,图片突然撑开。
  2. 性能问题。没有惰性渲染、惰性加载,多图页面会有潜在性能问题。
  3. 逐行渲染问题。标准 JPEG 格式压缩的图片,下载时基线 JPEG 算法会逐行渲染图片,影响体验。

布局偏移

对于问题 1. 我们为图片设置好宽高即可:

<style>
img {
max-width: 100%;
height: auto;
}
</style>
<img height="853" width="1280" />

性能相关

content-visibility: auto

该 CSS 属性会告知浏览器,在图片接近屏幕前,先不要为其布局。浏览器也不会去解码用户暂时看不见的图片,节省 CPU。

loading="lazy"

该属性会告知浏览器,在图片接近屏幕前,先不要去请求图片资源。

decoding="async"

该属性会给浏览器脱离主线程解码图片的权限,避免用来解码图片的 CPU 时间影响用户。

呈现相关

渐进加载

直观体验:

上边两个例子在加载大图时,都用到了低质量图片占位(Low Quality Image Placeholder, LQIP)。在大图加载时,展示模糊的低质量图片,在加载低质量图片时,展示背景色。图片加载成功时,配合 transition 效果,整个过程显得顺滑流畅。 José M. Pérez 在 2015 年写了一篇文章详细分析了 Medium 图片渐进加载细节。

了解基本思路后,实现方式可以有很多种。其中关键,需要准备高清图对应的低质量图片,以及对低质量图片进行模糊处理。

低质量图片

BBKi.ng 所有图片均存放在阿里云 OSS 中。OSS 数据处理下的图片处理功能可以创建样式。不同样式对应不同的图片处理细节,如图片格式转换、图片质量、缩略等。我们可以新建名为 LQIP 的样式,将原图压缩为低质量图片。假设上传原图后得到的地址为:url/to/my-awesome-picture.jpg, 那么通过地址 url/to/my-awesome-picture.jpg?x-oss-process=style/LQIP 即能获取低质量图片。

模糊效果

实现图片模糊有很多种方式。比如

  1. CSS 滤镜
  2. CSS 背景滤镜
  3. Canvas 渲染(blurhash
img {
filter: blur(2px)
}

.cover {
backdrop-filter: blur(2px);
}

以上几种方式都各有优缺点。CSS 滤镜优点是写法比较简单,也无需引入新的元素。缺点是,边缘也会模糊掉。可以增加一个包裹元素,设置 overflow: hidden 解决,但是模糊半径较大时,图片边缘的模糊效果始终不是很理想(效果对比);用 CSS 背景滤镜可以得到锐利清晰的边缘,同时图片内容区域模糊效果也很好,缺点是效果是应用在元素背后的区域,因此我们需要引入额外的元素,同时该样式会影响图层合成时间、默认不兼容火狐浏览器;Blurhash 方法的优点是模糊图片只需要用简洁哈希字符串表示,节省空间。缺点是编码解码过程稍显繁琐。同时客户端解码大尺寸图片时也存在性能问题。

综合考虑后,最终使用背景滤镜对图片进行模糊处理。

示例

参考链接