图标用 SVG 还是 PNG:看这三点

设计与前端发布于 2026-10-31

默认答案是 SVG。但「默认」不等于「永远」,三条判据能覆盖绝大多数场景。

判据一:这个图标需要变颜色吗

要变色的图标必须用 SVG,而且必须内联。

外链的 SVG 有个反直觉的限制:

<!-- 这个图标没法用 CSS 改颜色 -->
<img src="icon.svg">

因为 <img> 里的 SVG 是独立文档,外部 CSS 进不去。想让图标跟随主题色(比如 hover 时变主色),要么内联:

<svg viewBox="0 0 24 24">
  <path d="..." fill="currentColor" />
</svg>

要么用 CSS mask:

.icon {
  background-color: var(--brand);
  mask: url(icon.svg) center / contain no-repeat;
}

第二条路适合「同一个图标要在很多地方用、又都要变色」的场景,缺点是多一层背景色逻辑,透明区域的表现容易出意外。

内联 SVG 的关键是 fill="currentColor" —— 它让图标继承父元素的 color,于是主题切换、hover、禁用态全都自动跟随,不用改图片文件。

这一条是很多「暗色主题下图标看不见」问题的根因:图标是黑色 PNG,暗底上自然消失。

判据二:放大到什么尺寸

SVG 无限缩放不失真;PNG 放大就是插值糊。

一个常见的错误是:为了高清屏导出 4 倍图(比如 96×96 显示成 24×24),于是所有图标都变成大文件。几十个图标加起来,比 SVG 大一个数量级。

显示尺寸 PNG 需要 SVG
16~32px 1x + 2x 两套 一个够
48~128px 2 倍图 一个够
打印 / 大幅面 不现实 唯一选择

判据三:内容是「形状」还是「画面」

SVG 擅长几何形状:线条、单色填充、简单渐变。不擅长:

  • 照片级写实插画(几万个路径点,文件比 PNG 还大)
  • 复杂滤镜、混合模式(浏览器渲染差异大)
  • 依赖特定字体的文字(对方没装这个字体就变形,正确做法是转成路径)

所以「插画」和「照片」用位图,「UI 图标」用 SVG,界线大致在这里。

常见失误清单

导出 SVG 时尺寸写死

<svg width="48" height="48" viewBox="0 0 24 24">

width/height 只是默认显示尺寸,缩放在 viewBox 里。但很多设计工具导出时会只留 width/height、不留 viewBox,于是这个 SVG 一旦被放大就糊 —— 因为它已经退化成位图逻辑。

检查方法:打开 SVG 源文件搜 viewBox。没有它就是这个图标不可缩放。

反过来,如果 viewBox 比图形小(比如图形超出 24×24),图标会被裁掉一块,而在设计稿里看不出来 —— 设计软件会把画布外的东西也显示出来。

用 width: 100% 撑满容器

SVG 默认按比例缩放,但父容器如果没有明确尺寸,width:100% 可能让它变得巨大或者塌成 0。给一个显式的 width/height 或 aspect-ratio 更稳。

把图标做成字体

图标字体(iconfont)在 2020 年前后很流行,现在不建议:

  • 字符渲染受字体加载影响,会出现空白方块
  • 无法做多色
  • 屏幕阅读器会把它读成一个字符(需要额外 aria 处理)
  • 抗锯齿表现不如 SVG

存量项目可以慢慢替换,新项目别再用。

位图图标用 JPEG

JPEG 不支持透明,图标背景会变成白块或黑块。要位图就用 PNG 或 WebP。

WebP 的位置

WebP 支持透明、体积比 PNG 小 20%~30%,浏览器支持已经很完整。它适合「必须用位图的图标」—— 比如带复杂渐变或阴影的图标。

但 WebP 不适合当 favicon(部分系统不认),也不适合需要被设计软件二次编辑的素材。

批量处理

把一批 PNG 图标转 WebP 或统一尺寸,用图片格式转换;只需要改尺寸和质量的用图片压缩与缩放,支持批量按最长边缩放。

如果图标要加统一底标或型号水印,图片加水印可以批量做。


结论

场景 选
UI 图标、导航图标、按钮图标 内联 SVG + currentColor
需要复用、又要变色 SVG + CSS mask
复杂插画、截图、照片 PNG 或 WebP
favicon 见专门那篇
要导出给非设计人员用的图 PNG(兼容性最好)

一句话:能在代码里改的用 SVG,只能是「一张图」的用位图。