SVG vs Icon Fonts
SVG is the modern standard:
- - Better accessibility (native ARIA support)
- No flash of invisible/wrong icon (FOIT)
- Multicolor support
- Smaller bundles with tree-shaking
Only consider icon fonts for legacy IE11 support.
Accessibility Patterns
Decorative icons (next to visible text):
CODEBLOCK0
Informative icons (standalone, no label):
CODEBLOCK1
SVG with accessible name:
CODEBLOCK2
Key rules:
- -
aria-hidden="true" on SVGs that duplicate visible text - INLINECODE1 prevents unwanted tab stops in IE/Edge
- INLINECODE2 must be first child inside
<svg> for screen reader support - IDs must be unique if multiple SVGs are inline
Color Inheritance
CODEBLOCK3
INLINECODE4 inherits from CSS color property. The icon changes color with hover states automatically:
CODEBLOCK4
Remove hardcoded fill="#000" from SVGs before using currentColor.
For stroke-based icons, use stroke="currentColor" instead.
Sizing
Standard grid sizes: 16, 20, 24, 32px
Match stroke weight to size:
| Size | Stroke | Use case |
|---|
| 16px | 1px | Dense layouts, small text |
| 20px |
1.25px | Default UI |
| 24px | 1.5px | Buttons, primary actions |
| 32px | 2px | Headers, navigation |
Touch targets need 44x44px minimum—icon can be smaller if tappable area is larger via padding.
CODEBLOCK5
Scaling with Text
CODEBLOCK6
Icon scales with surrounding text size automatically.
Symbol Sprites
For many repeated icons, reduce DOM nodes with sprites:
CODEBLOCK7
External sprites (<use href="/icons.svg#search"/>) don't work in older Safari without polyfill.
Performance
Benchmark (1000 icons):
- -
<img> with data URI: 67ms (fastest) - Inline SVG optimized: 75ms
- Symbol sprite: 99ms
- INLINECODE10 external: 76ms
Recommendations:
- - Tree-shake icon libraries (Lucide, Heroicons support this)
- Don't import entire Font Awesome (1MB+)—use subset or switch to SVG
- Inline critical icons, lazy-load sprite for non-critical
Consistency
- - Stick to one icon set—mixing styles looks unprofessional
- Match icon stroke weight to your font weight (regular text = 1.5px stroke)
- Pick one style per context: outlined for inactive, filled for active
- Optical alignment differs from mathematical—circles reach edges, squares don't
- Name icons by appearance, not meaning:
stopwatch not INLINECODE12
Common Mistakes
- - Missing
aria-hidden on decorative icons—screen readers announce gibberish - Mixing rounded and sharp icon styles in same interface
- Giant icon libraries for 10 icons—massive bundle bloat
- Icon-only buttons without accessible name—impossible to use with screen readers
- Hardcoded colors preventing theme switching
- Stroke width not scaling with icon size—16px icon with 2px stroke looks heavy
SVG 与图标字体
SVG 是现代标准:
- - 更好的可访问性(原生 ARIA 支持)
- 无不可见/错误图标闪烁(FOIT)
- 支持多色
- 通过摇树优化实现更小的包体积
仅在需要支持旧版 IE11 时考虑使用图标字体。
可访问性模式
装饰性图标(位于可见文本旁):
html
信息性图标(独立使用,无标签):
html
带有可访问名称的 SVG:
html
关键规则:
- - 在重复可见文本的 SVG 上使用 aria-hidden=true
- focusable=false 可防止 IE/Edge 中出现不必要的 Tab 焦点
- 必须是
- 如果内联多个 SVG,ID 必须唯一
颜色继承
svg
currentColor 从 CSS color 属性继承。图标会随悬停状态自动变色:
css
.button { color: blue; }
.button:hover { color: red; } / 图标也变为红色 /
在使用 currentColor 之前,移除 SVG 中硬编码的 fill=#000。
对于基于描边的图标,改用 stroke=currentColor。
尺寸调整
标准网格尺寸:16、20、24、32px
将描边粗细与尺寸匹配:
| 尺寸 | 描边 | 使用场景 |
|---|
| 16px | 1px | 密集布局、小号文字 |
| 20px |
1.25px | 默认 UI |
| 24px | 1.5px | 按钮、主要操作 |
| 32px | 2px | 标题、导航 |
触摸目标至少需要 44x44px——如果通过内边距扩大可点击区域,图标可以更小。
css
.icon-button {
width: 24px;
height: 24px;
padding: 10px; / 创建 44x44 的触摸目标 /
}
随文字缩放
css
.icon {
width: 1em;
height: 1em;
}
图标会自动随周围文字大小缩放。
符号精灵
对于大量重复图标,使用精灵减少 DOM 节点:
html
外部精灵(
性能
基准测试(1000 个图标):
- -
使用 data URI:67ms(最快) - 优化的内联 SVG:75ms
- 符号精灵:99ms
外部引用:76ms
建议:
- - 对图标库进行摇树优化(Lucide、Heroicons 支持此功能)
- 不要导入整个 Font Awesome(1MB+)——使用子集或切换到 SVG
- 内联关键图标,对非关键图标进行懒加载精灵
一致性
- - 坚持使用一套图标集——混搭风格显得不专业
- 将图标描边粗细与字体粗细匹配(常规文字 = 1.5px 描边)
- 每个上下文选择一种风格:非活跃状态用轮廓线,活跃状态用填充
- 光学对齐不同于数学对齐——圆形到达边缘,方形则不会
- 按外观命名图标,而非含义:stopwatch 而非 speed
常见错误
- - 装饰性图标缺少 aria-hidden——屏幕阅读器会读出乱码
- 在同一界面中混用圆角和直角图标风格
- 为仅使用 10 个图标引入大型图标库——导致包体积严重膨胀
- 仅图标按钮没有可访问名称——屏幕阅读器无法使用
- 硬编码颜色导致无法切换主题
- 描边宽度未随图标尺寸缩放——16px 图标搭配 2px 描边显得笨重