Web 图标

最后更新: 2022-09-26 18:12:04 +0800 +0800
tags: Web | Icons
原文以英文撰写。您正在阅读AI翻译版本。

Web 图标可以是文本字形、SVG 图形或位图图像。格式选择会影响渲染保真度、缓存、样式、安全性,以及外围控件公开的无障碍名称。

将图标字体视为字体 #

图标字体将字符代码或连字映射为象形图:

html
<span class="material-icons" aria-hidden="true">add_location</span>

字形会继承 color、font-size 和其他文本属性,因此一个字体文件可以为整套单色图标设置主题。相同的依赖关系也带来了限制:

  • 字体被阻止或延迟加载时,会显示缺失字形方框或后备文本。
  • 替换字体的用户样式可能移除图标。
  • 私用区码位不具备可互操作的文本含义。
  • 辅助技术可能会朗读连字名称。
  • 字体平滑和微调可能改变小尺寸下的形状。

应从无障碍树中隐藏装饰性字体字形,并把无障碍名称放在其控件上:

html
<button type="button" aria-label="Add location">
  <span class="material-icons" aria-hidden="true">add_location</span>
</button>

不要仅在生成的 ::before 内容中放置必需标签。字体加载、自定义样式和无障碍 API 都可能移除该信息通道。

考虑 Unicode 字形差异 #

Unicode 符号携带的是标准化字符标识,而非标准化图标设计。所选字体决定其轮廓、度量,以及它会渲染为单色文本还是彩色表情符号。变体选择符可以要求某些字符以文本或表情符号形式呈现,但不同平台仍可能使用不同图稿。

当字符本身属于文本内容时(例如数学运算符或方向箭头),应使用 Unicode。不要把外观相似的字符用作应用特定操作的唯一标签。屏幕阅读器会朗读该字符的语义,而其语义可能与预期操作不符。

选择 SVG 集成模型 #

SVG 描述与分辨率无关的形状,并支持多种填充、描边、渐变和动画。集成方式决定样式和安全行为。

内联 SVG #

内联标记参与文档层叠:

html
<button type="button">
  <svg
    aria-hidden="true"
    focusable="false"
    width="20"
    height="20"
    viewBox="0 0 20 20">
    <path fill="currentColor" d="M3 10l4 4L17 4"></path>
  </svg>
  Save
</button>

currentColor 跟随按钮的文本颜色。同一个复杂图标多次出现时,内联标记会增加 HTML 大小,但它支持直接设置样式,并避免单独的图像请求。

有意义的独立图形需要无障碍名称:

html
<svg role="img" aria-labelledby="network-title" viewBox="0 0 24 24">
  <title id="network-title">Network topology</title>
  <circle cx="12" cy="12" r="8"></circle>
</svg>

装饰性 SVG 应改用 aria-hidden="true" 和 focusable="false"。对于仅包含图标的按钮,应命名按钮本身,因为按钮才是交互对象。

SVG 精灵图 #

内联精灵图定义可复用的符号:

html
<svg aria-hidden="true" hidden>
  <symbol id="icon-check" viewBox="0 0 24 24">
    <path d="M4 12l5 5L20 6"></path>
  </symbol>
</svg>

<svg aria-hidden="true" focusable="false">
  <use href="#icon-check"></use>
</svg>

同源外部精灵图将定义移入可缓存文件:

html
<svg aria-hidden="true" focusable="false">
  <use href="/icons/sprite.svg#icon-check"></use>
</svg>

浏览器有意限制对克隆的 <use> 内容设置样式。应在符号内放置 fill="currentColor" 或稳定的呈现属性,并为外层 <svg> 设置样式。即使服务器返回 CORS 标头,跨源外部片段也不具备可移植性,因此应从同源提供精灵图,或者获取、验证并内联精灵图。

将 SVG 用作图像 #

通过 <img> 加载的 SVG 是隔离的图像文档:

html
<img src="/icons/product-mark.svg" alt="Example product">

页面 CSS 无法访问其内部路径,currentColor 也不会从宿主元素继承。图像上下文会禁用脚本,因此与注入 SVG 标记相比,使用 <img> 加载可信静态资源更安全。空的 alt="" 表示装饰性图像;有意义的图像需要替代文本。

任意 SVG 标记在内联嵌入或作为可导航文档提供时,应视为活动内容。应清理不受信任的文件,禁止脚本和事件处理器属性,控制外部引用,并使用预期的媒体类型和适当的内容安全策略提供文件。

按显示密度调整位图图标大小 #

PNG、WebP 或 AVIF 可以保留设计像素、多色细节,以及难以用矢量图重现的效果。位图放大时无法增加细节,因此应提供不同密度的变体:

html
<img
  src="/icons/avatar-24.png"
  srcset="/icons/avatar-24.png 1x, /icons/avatar-48.png 2x"
  width="24"
  height="24"
  alt="">

显式尺寸会预留布局空间。对高密度源图进行下采样可以生成清晰的小图标,但大尺寸密度变体会消耗带宽和内存。像素画图标可能需要 image-rendering 规则和整数缩放;照片或带纹理的图标应根据所需的 Alpha 通道和压缩行为选择图像格式。

CSS 背景图像适合装饰用途,因为它们不会提供无障碍名称:

css
.status::before {
  background: url("/icons/status.svg") center / contain no-repeat;
  content: "";
}

当背景传达状态时,应将文本标签保留在 DOM 中。

根据语义和交付约束进行选择 #

应使用满足实际契约的表示形式:

要求合适的表示形式
字符属于正文使用经过测试的后备字体栈显示 Unicode 字形
需要直接设置样式的单色 UI 图标内联 SVG 或同源 SVG 精灵图
无需宿主样式的可缓存静态矢量图通过 <img> 加载 SVG
多色矢量标志SVG 图像或经过谨慎限定作用域的内联 SVG
照片或按像素设计的细节感知密度的位图
现有的旧版图标字体系统配有后备方案和无障碍测试的图标字体

可缓存性可能有利于使用一个外部精灵图或图像;组件隔离可能有利于内联 SVG;严格的内容安全策略可能有利于加载惰性图像而不是注入标记。格式本身不提供语义。装饰性图标必须对辅助技术保持隐藏,而控件和有意义的图形需要即使资源加载失败仍可用的无障碍名称。

评论

在 GitHub 上阅读或评论(发表评论需要登录)