草庐IT

现代图片性能优化及体验优化指南 - 图片资源的容错及可访问性处理

ChokCoco 2023-03-28 原文

本文是系列第五篇,终章。系列文章:

  1. 现代图片性能优化及体验优化指南 - 图片类型及 Picture 标签的使用
  2. 现代图片性能优化及体验优化指南 - 响应式图片方案
  3. 现代图片性能优化及体验优化指南 - 缩放精细化展示及避免布局偏移、拉伸
  4. 现代图片性能优化及体验优化指南 - 懒加载及异步图像解码方案

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

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

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

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 信息:

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 下,我们可能得到如下的结果:

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

总结一下

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

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

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

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

最后

OK,本文到此结束,希望本文对你有所帮助 ?

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

有关现代图片性能优化及体验优化指南 - 图片资源的容错及可访问性处理的更多相关文章

  1. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  2. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  3. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  4. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  5. ruby-on-rails - Rails 3,在RAILS_ROOT上方显示来自本地文件系统的jpg图片 - 2

    我正在尝试找出一种方法来显示来自不在RAILS_ROOT下(在RedHat或Ubuntu环境中)的已安装文件系统的图像。我不想使用符号链接(symboliclink),因为这个应用程序实际上是通过Tomcat部署的,而当我关闭Tomcat时,Tomcat会尝试跟随符号链接(symboliclink)并删除挂载中的所有图像。由于这些文件的数量和大小,将图像放在public/images下也不是一种选择。我查看了send_file,但它只会显示一张图片。我需要在一个格式良好的页面中显示6个请求的图像。由于膨胀,我宁愿不使用Base64编码,但我不知道如何将图像数据与呈现的页面一起传递下去。

  6. Ruby 和指南针路径与 yeoman 项目 - 2

    我安装了ruby​​、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom

  7. ruby - 如何找到我的 Ruby 应用程序中的性能瓶颈? - 2

    我编写了一个Ruby应用程序,它可以解析来自不同格式html、xml和csv文件的源中的大量数据。我如何找出代码的哪些区域花费的时间最长?有没有关于如何提高Ruby应用程序性能的好资源?或者您是否有任何始终遵循的性能编码标准?例如,你总是用加入你的字符串吗?output=String.newoutput或者你会使用output="#{part_one}#{part_two}\n" 最佳答案 好吧,有一些众所周知的做法,例如字符串连接比“#{value}”慢得多,但是为了找出您的脚本在哪里消耗了大部分时间或比所需时间更多,您需要进行分

  8. 西安华为OD面试体验 - 2

    西安华为OD面试体验开始投简历技术面试进展工作进展开始投简历去年一整年一直在考研和工作之间纠结,感觉自己的状态好像当时的疫情一样差劲。之前刚毕业的时候投了个大厂的简历,结果一面写算法的时候太拉跨了,虽然知道时dfs但是代码熟练度不够,放在平时给足时间自己可以调试通过,但是熟练度不够那面试当时就写不出来被刷了。说真的算法学到后期我感觉最重要的是熟练度和背板子(对于我这种普通玩家来说),面试题如果一上来短时间内想不出思路就完蛋了。然后由于当时找的工作不是很理想就又想考研了。但是考研是有风险的,我自我感觉自己可能冲不上那个学校,而找工作一个没成可以继续找嘛。本着抱着试试看的态度在boss上投了简历,

  9. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  10. Simulink方法总结和避坑指南(一)——Simulink入门与基本调试方法 - 2

    文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景  最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。  在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记

随机推荐