跳到正文
SvgJsx
语言: 中文

如何在 React 中使用 SVG 图标

在 React 应用中使用 SVG 图标有五种常见方式。本指南从性能、样式和无障碍三个方面进行比较,并说明每种方式适合的场景。

快速预设:
将 .svg 文件拖放到这里,或文件通过 FileReader 在本地读取,绝不会上传。
选项
导出方式:
import type { SVGProps } from "react";

const HeartIcon = ({ size = 24, ...props }: SVGProps<SVGSVGElement> & { size?: number | string }) => (
  <svg viewBox="0 0 24 24" className="icon icon-heart" width={size} height={size} {...props}>
    <g id="Layer_1" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M19.0001 14.0002c1.4900-1.4600 3.0000-3.2100 3.0000-5.5000A5.5000 5.5000 0 0 0 16.5000 3c-1.7600 0-3.0000.5000-4.5000 2-1.5000-1.5000-2.7400-2-4.5000-2A5.5000 5.5000 0 0 0 2 8.5000c0 2.3000 1.5000 4.0500 3 5.5000l7 7Z" style={{ fillOpacity: "0.15", fill: "currentColor" }} />
    </g>
  </svg>
);

export default HeartIcon;

预览

转换后 SVG 的预览
原始 SVG
706 B
优化后 SVG
548 B(-22%)
组件
692 B

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)。

常见问题

在 React 中使用 SVG 图标的最佳方式是什么?

对于界面图标,带 currentColor 和 size 属性的内联组件最灵活。静态插画用 <img>,如果图标库的风格符合你的设计,也可以直接使用图标库。

内联 SVG 图标会影响性能吗?

很少。一个典型的 24×24 图标优化后只有 300–600 字节。只有同时渲染数百个复杂图标时才会出现问题,这时雪碧图或 <img> 更合适。

应该用 SVGR 还是手动转换图标?

SVGR 适合规模大、变动频繁且构建流程稳定的图标集。预先转换好的组件不需要任何配置,在所有打包工具中表现一致。

如何让 SVG 图标符合无障碍要求?

用 aria-hidden="true" 隐藏装饰性图标,为有意义的图标提供 aria-label 或 <title> 作为可访问名称。不要仅依靠图标传达关键信息。

如何用 Tailwind 设置 SVG 图标尺寸?

移除固定的 width 和 height,保留 viewBox,然后使用 size-5 或 h-4 w-4 等类。也可以开启 size 属性并传入数字。