Web 图标可以是文本字形、SVG 图形或位图图像。格式选择会影响渲染保真度、缓存、样式、安全性,以及外围控件公开的无障碍名称。
将图标字体视为字体 #
图标字体将字符代码或连字映射为象形图:
<span class="material-icons" aria-hidden="true">add_location</span>字形会继承 color、font-size 和其他文本属性,因此一个字体文件可以为整套单色图标设置主题。相同的依赖关系也带来了限制:
- 字体被阻止或延迟加载时,会显示缺失字形方框或后备文本。
- 替换字体的用户样式可能移除图标。
- 私用区码位不具备可互操作的文本含义。
- 辅助技术可能会朗读连字名称。
- 字体平滑和微调可能改变小尺寸下的形状。
应从无障碍树中隐藏装饰性字体字形,并把无障碍名称放在其控件上:
<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 #
内联标记参与文档层叠:
<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 大小,但它支持直接设置样式,并避免单独的图像请求。
有意义的独立图形需要无障碍名称:
<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 精灵图 #
内联精灵图定义可复用的符号:
<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>同源外部精灵图将定义移入可缓存文件:
<svg aria-hidden="true" focusable="false">
<use href="/icons/sprite.svg#icon-check"></use>
</svg>浏览器有意限制对克隆的 <use> 内容设置样式。应在符号内放置 fill="currentColor" 或稳定的呈现属性,并为外层 <svg> 设置样式。即使服务器返回 CORS 标头,跨源外部片段也不具备可移植性,因此应从同源提供精灵图,或者获取、验证并内联精灵图。
将 SVG 用作图像 #
通过 <img> 加载的 SVG 是隔离的图像文档:
<img src="/icons/product-mark.svg" alt="Example product">页面 CSS 无法访问其内部路径,currentColor 也不会从宿主元素继承。图像上下文会禁用脚本,因此与注入 SVG 标记相比,使用 <img> 加载可信静态资源更安全。空的 alt="" 表示装饰性图像;有意义的图像需要替代文本。
任意 SVG 标记在内联嵌入或作为可导航文档提供时,应视为活动内容。应清理不受信任的文件,禁止脚本和事件处理器属性,控制外部引用,并使用预期的媒体类型和适当的内容安全策略提供文件。
按显示密度调整位图图标大小 #
PNG、WebP 或 AVIF 可以保留设计像素、多色细节,以及难以用矢量图重现的效果。位图放大时无法增加细节,因此应提供不同密度的变体:
<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 背景图像适合装饰用途,因为它们不会提供无障碍名称:
.status::before {
background: url("/icons/status.svg") center / contain no-repeat;
content: "";
}当背景传达状态时,应将文本标签保留在 DOM 中。
根据语义和交付约束进行选择 #
应使用满足实际契约的表示形式:
| 要求 | 合适的表示形式 |
|---|---|
| 字符属于正文 | 使用经过测试的后备字体栈显示 Unicode 字形 |
| 需要直接设置样式的单色 UI 图标 | 内联 SVG 或同源 SVG 精灵图 |
| 无需宿主样式的可缓存静态矢量图 | 通过 <img> 加载 SVG |
| 多色矢量标志 | SVG 图像或经过谨慎限定作用域的内联 SVG |
| 照片或按像素设计的细节 | 感知密度的位图 |
| 现有的旧版图标字体系统 | 配有后备方案和无障碍测试的图标字体 |
可缓存性可能有利于使用一个外部精灵图或图像;组件隔离可能有利于内联 SVG;严格的内容安全策略可能有利于加载惰性图像而不是注入标记。格式本身不提供语义。装饰性图标必须对辅助技术保持隐藏,而控件和有意义的图形需要即使资源加载失败仍可用的无障碍名称。
评论
在 GitHub 上阅读或评论(发表评论需要登录)