图标的交付方式会影响性能、无障碍,以及设计师改动它们的难易程度。这个领域的变化已经大到"旧建议正在起反作用"的程度。

图标字体:基本属于遗留方案

把图标做成字体文件里的字形,通过 CSS 伪元素渲染。

当年流行的原因:只需一次 HTTP 请求、可用颜色和字号控制、可缩放

失宠的原因:

  • 无障碍问题:读屏软件可能把私用区字符念成乱码;字体加载失败时还会渲染出毫不相干的字符。
  • 只能单色(除非用叠加字形之类的技巧)。
  • 阻塞行为:字体加载失败或缓慢,图标就会缺失或被错误替换。
  • 整包成本:不精心做子集化的话,为了用十二个图标而发出几百个。
  • 渲染:图标按文字方式抗锯齿,在某些字号下看起来会有点怪。

只在迁移不划算的遗留代码库里继续保留它。

CSS 雪碧图:小众但仍活着

把许多图标放进一张位图,用 background-position 定位。

仍然合理的场景:你的图标确实是位图(照片、复杂渐变、多色插画),或者你要支持限制 SVG 的环境。

缺点:分辨率固定,高清屏需要 2 倍版本;维护麻烦(改一处就要重新生成整张图并改动坐标);无法按图标改色;用一个图标也要下载全部。

要注意的是,HTTP/2 和 HTTP/3 已经消除了它最初的动机——请求数不再昂贵——所以雪碧图如今是个小众选择,而不是性能技巧。

SVG:默认选择

矢量图标,可以内联在标记里,也可以通过 use 引用 SVG 雪碧文件。

优势:

  • 任何尺寸和 DPI 下都锐利,不需要 2 倍版本。
  • 可用 CSS 定制——用 currentColor 控制颜色、悬停态、单独控制局部,甚至做动画。
  • 可访问:用 title 元素或 aria-label 明确图标含义,用 aria-hidden 隐藏纯装饰图标。
  • 优化后极小:多数界面图标能压到几百字节。
  • 支持多色和渐变。

取舍:

  • 内联 SVG 不会被单独缓存——它是 HTML 的一部分,跨页面重复的图标会被反复发送。十几个图标无所谓;有几百个就该考虑 SVG 雪碧文件或复用 symbol 的组件。
  • 直接粘贴未优化的编辑器导出会造成标记膨胀。图标要过一遍优化器,去掉编辑器元数据、隐藏图层和过高的数值精度。
  • 对用户上传的 SVG 做净化。 SVG 可以包含脚本,绝不要内联不可信的文件。

实用建议

界面图标用内联 SVG;同一批图标在多个页面重复时用 SVG 雪碧文件;只有真正的照片类素材才用位图雪碧图。无论选哪种,都要逐个判断该图标是有意义的(需要可访问的名称)还是装饰性的(应对辅助技术隐藏)——仅这一个习惯,就能解决大部分图标的无障碍问题。