1. 内联 SVG 组件
把每个图标转换成组件(也就是本站自动化的方式)能让你完全掌控:图标通过 currentColor 继承颜色,接收 size、className 等 props,并能用 CSS 或动画库实现动画。打包工具会对未使用的组件做 tree-shaking,所以只有被导入的图标才会被打包。
代价是这些标记会成为 JavaScript 包的一部分。几十个小图标的影响可以忽略不计,但数百个复杂插画就不一样了。
2. img 标签与 CSS 背景
<img src="/logo.svg" alt="Company"> 是最简单的方式,浏览器还能缓存文件。但这种 SVG 与你的 CSS 是隔离的,无法在悬停或深色模式下改变颜色。它适合 Logo 和内容固定的插画。
3. SVGR 与构建时 loader
SVGR(通过 @svgr/webpack 或 vite-plugin-svgr)会在构建时把 .svg 导入转换为组件。对大型图标目录来说很方便,但需要额外的构建配置,而且在不同打包工具和 Turbopack 之间表现可能不一致。用本工具一次性转换,可以得到同类组件,并作为源代码直接提交。
4. SVG 雪碧图与 5. 图标库
雪碧图把许多 <symbol> 元素放在一个文件中,再通过 <use href="#icon"> 引用。它能让 HTML 保持精简,但会让服务端渲染变得复杂。Lucide、Heroicons、Phosphor 等图标库提供现成的组件,如果它们的风格与你的设计一致,就是理想之选。
无论选择哪种方式,都请遵守以下无障碍规则:
- 紧挨文字的装饰性图标加上 aria-hidden="true"。
- 独立使用的图标(例如只有图标的按钮)需要可访问名称:在按钮上设置 aria-label,或在 SVG 中加入 <title>。
- 保留 viewBox,并用 em 或 rem 设置图标尺寸,使其随用户字号缩放。
- 有意义的图标与背景的对比度至少为 3:1(WCAG 1.4.11)。