图片资源,在我们的业务中可谓是占据了非常大头的一环,尤其是其对带宽的消耗是十分巨大的。

对图片的性能优化及体验优化在今天就显得尤为重要。本文,就将从各个方面阐述,在各种新特性满头飞的今天,我们可以如何尽可能的对我们的图片资源,进行性能优化及体验优化。

图片资源的容错及可访问性处理

OK,最后一个章节,我们简单聊一聊图片资源的容错及可访问性处理。

图片的可访问性处理

可访问性(A11Y),在我们的网站中,属于非常重要的一环,但是大部分同学都容易忽视它。

在一些重交互、重逻辑的网站中,我们需要考虑用户的使用习惯、使用场景,从高可访问性的角度考虑,譬如假设用户没有鼠标,仅仅使用键盘,能否顺畅的使用我们的网站?

非常重要的一点是,提高可访问性也能让普通用户更容易理解 Web 内容

基于 [Usability & Web Accessibility - image][]

对于图像信息,我们需要大致遵循如下可访问性原则:

  • 所有有意义的 img 元素必须有 alt 属性
  • 提供替代 alt 属性的其他方式
  • 使用辅助技术隐藏装饰图像

第一点非常好理解,所有的有意义的图片元素都必须要提供 alt 属性。

第二点比较有意思,在 A11Y 中,其实有一套 [WAI-ARIA 标准][]。WAI-ARIA 是一个为残疾人士等提供无障碍访问动态、可交互Web内容的技术规范。

简单来说,它提供了一些属性,增强标签的语义及行为:

  • 可以使用 tabindex 属性控制元素是否可以聚焦,以及它是否/在何处参与顺序键盘导航
  • 可以使用 role 属性,来标识元素的语义及作用,譬如使用 <div id="saveChanges" tabindex="0" role="button">Save</div>来模拟一个按钮
  • 还有大量的 aria-* 属性,表示元素的属性或状态,帮助我们进一步地识别以及实现元素的语义化,优化无障碍体验

上述第二点,提供替代 alt 属性的其他方式 的含义就是使用 WAR-ARIA 规范提供的诸如 aria-labelaria-labelledby 属性为图像提供可访问的名称。

当存在这些属性时,辅助技术(屏幕阅读器)将忽略图像的 alt 属性并读取 ARIA 标签。

而第三点,使用辅助技术隐藏装饰图像,又是什么意思呢?

上面第一点 所有有意义的 img 元素必须有 alt 属性,反过来说,页面上也会存在无意义的装饰性的图片,这些图片内容对辅助技术(屏幕阅读器)而言,其实是可以忽略的。

对于没有任何功能或信息内容的装饰图像,可以通过多种方式对屏幕阅读器隐藏:

  • 使用空的 alt 属性
  • 使用 ARIA 属性 role="presentation" 标明图片元素是装饰可忽略图片
  • 使用 CSS background 的方式呈现这些图片

alt 不要与 title 混淆

OK,下面来讲一些有意思的细节内容。

有一个非常基础的知识,简单过一下,也就是图片元素中,alttitle 的差异:

  • 图片中的 alt 属性是在图片不能正常显示时出现的文本提示。
  • 图片中的 title 属性是在鼠标在移动到元素上的文本提示。

正确使用 alt 属性

对于使用屏幕阅读器的用户而言,图片是无法正常展示或者被的浏览的,基于此,我们需要利用好 alt 属性,或者是上述的aria-labelaria-labelledby 属性。

那么,这些属性内的内容应该填充什么呢?我们需要基于图片的功能加以区分:

  • [信息性图像][]:以图形方式表示概念和信息的图像,通常是图片、照片和插图。alt 替代文本应该至少是一个简短的描述,传达图像所呈现的基本信息。

  • [装饰性图像][]:当图像的唯一目的是为页面添加视觉装饰,而不是传达对理解页面很重要的信息时,如上述所言,使用空的 alt,譬如 alt=""

  • [功能图像][]:用作链接或按钮的图像的替代文本应该描述链接或按钮的功能,而不是视觉图像。此类图像的示例是表示打印功能的打印机图标或提交表单的按钮。

  • [文本图像][]:可读文本有时会出现在图像中。如果图片不是徽标,请避免图片中出现文字。但是,如果使用文本图像,替代文本应包含与图像中相同的词。

  • 图形和图表等[复杂图像:为了传达数据或详细信息,提供与图像中提供的数据或信息等效的完整文本作为替代文本。][]

  • [图像组][]:如果多张图像传达一条信息,则一张图像的替代文本应传达整组信息。

  • [图像映射][]:包含多个可点击区域的图像的替代文本应该为链接集提供整体上下文。此外,每个可单独点击的区域都应该有替代文本来描述链接的目的或目的地。

其实 alt 的学问是非常之多的,如果我们的页面能做到这一点,那真的算是从根上开始思考,开始优化用户体验。

img 元素与 background 元素的取舍

OK,那么,讲到这里,还有一个有意思的点就很自然的应该被提及。

那就是我们应该什么时候使用 <img> 元素,什么时候使用 background 内嵌图片?

我们可以从性能功能两个方面进行考虑:

类型

img

backgroud-image

图层位置

前景

背景

默认初始尺寸

不定

固定

是否会产生回流重绘

不会

图片加载失败

可以触发元素的 onerror 事件,展示 alt 属性

无法有效设置异常处理场景

使用场景

Logo、产品图片、广告图片

装饰性无语义内容等

其实性能上并不是核心考虑的点,因为上文我们也讲到了在今天可以大规模使用是 loading="lazy" 属性,图片可以进行原生支持的懒加载。

我们在考虑选取 <img> 还是 backgroud-image 的时候,更多的还是从图片功能上进行考虑。一般来说,作为修饰的且无语义的装饰性图片选择使用 background-image,而比较重要的与网页内容相关的就使用 <img> 标签。

由于有语义的图片使用 <img> 展示,它的一个好处在于,当图片加载失败的时候,可以触发元素的 onerror 事件,我们可以有效的利用这一点,对图片进行异常处理。

图片的异常处理

当图片链接挂了,加载失败了,我们比较好的处理方式应该是怎么样呢?

处理的方式有很多种。在张鑫旭老师的这篇文章中 – [图片加载失败后CSS样式处理最佳实践][] 有一个不错的实践。

核心思路为:

  1. 利用图片加载失败,触发 <img> 元素的 onerror 事件,给加载失败的 <img> 元素新增一个样式类
  2. 利用新增的样式类,配合 <img> 元素的伪元素,在展示默认兜底图的同时,还能一起展示 <img> 元素的 alt 信息
<img src="test.png" alt="Alt Info" onerror="this.classList.add('error');">
img.error { position: relative; display: inline-block; } img.error::before { content: ""; /** 定位代码 **/ background: url(error-default.png); } img.error::after { content: attr(alt); /** 定位代码 **/ }

我们利用伪元素 before ,加载默认错误兜底图,利用伪元素 after,展示图片的 alt 信息:

image

OK,到此,完整的对图片的处理就算完成了,这也比较好的阐述了为什么,对有语义,有 alt 信息的图片,我们应该使用 <img> 元素来实现。这是因为,我们可以在错误发生的时候,比较好的对图片进行兜底展示,让用户直观的能够看到 alt 内容。

完整的 Demo 你可以戳这里看看:

[CodePen Demo – 图片处理][]

当然,上述方案存在两个小问题:

  1. 对于每一个 <img> 元素,我们都需要写一段 onerror="this.classList.add('error');" 代码,有点重复。因此,这个工作也可以交给 JavaScript 全局性的完成,并且,我们可能需要判断 alt 的值是否为空,在为空时,使用默认图片 alt 兜底文案。
  2. 早年间,<img> 等替换元素是没有伪元素的,后面 Chrome/Firefox 浏览器逐渐支持了当,<img> 的 src 拉取失败时,支持 <img> 元素的伪元素展示,这才有了上述的方案,但是,目前 Safari 仍不支持这个特性,所以,在 Safari 下,我们可能得到如下的结果:

image

效果仍然还是 OK 的,只是没有了兜底图的展示,在实际使用过程中,需要知道这一点。

总结一下

本章节,对图片资源的容错及可访问性处理进行了阐述。核心内容在于:

  1. 对于图像信息,我们需要大致遵循如下可访问性原则:
    • 所有有意义的 img 元素必须有 alt 属性
    • 提供替代 alt 属性的其他方式
    • 使用辅助技术隐藏装饰图像
  2. 正确使用 alt 属性,了解不同场景下 alt 应该填充什么内容
  3. img 元素与 background 元素的取舍
  4. 图片异常处理的最佳实践

至此,整个[现代图片性能优化及体验优化指南][]到此就圆满结束,整个系列的文章囊括了非常多的新的规范及特性,需要大家在实践中根据实际情况灵活选取使用。

同时,我们也应该能看到,前端技术仅仅在这一小个领域,都在不断的迭代创新。虽然很难,还是需要不断充实自己跟上新的潮流。共勉。