一、基本语法对比
1. 使用 <img>
标签
html
<img src="example.svg" alt="示例 SVG" width="200" height="200">
2. 使用 <svg>
标签(内联)
html
<svg width="200" height="200" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="50" fill="blue" />
</svg>
或内嵌外部 SVG 文件内容(也可通过 <use>
引用)。
二、核心区别对比表
特性 | <img> 标签加载 SVG |
<svg> 标签(内联) |
---|---|---|
是否 DOM 可访问 | ❌ 不可访问内部元素 | ✅ 可通过 JS/CSS 操作内部元素 |
CSS 样式控制 | ❌ 不能单独控制内部图形样式 | ✅ 可对 <path> 、<circle> 等单独设样式 |
JavaScript 交互 | ❌ 无法绑定事件到 SVG 内部元素 | ✅ 可为每个图形元素绑定事件(如点击、悬停) |
动画支持 | ❌ 无法使用 SMIL 或 CSS 动画控制内部 | ✅ 支持 CSS 动画、SMIL、JS 动画 |
可访问性(a11y) | ⚠️ 仅能通过 alt 属性提供描述 |
✅ 可使用 <title> 、<desc> 、ARIA 等增强语义 |
文件复用性 | ✅ 适合复用、缓存 | ❌ 内联会增加 HTML 体积(但可 <use> 复用) |
SEO 友好性 | ⚠️ 搜索引擎可能不解析 SVG 内容 | ✅ 内容可被搜索引擎索引(尤其含文本时) |
缩放/响应式 | ✅ 支持(依赖 viewBox ) |
✅ 更灵活,可配合 CSS 媒体查询 |
跨域限制 | ⚠️ 受 CORS 限制(如来自 CDN) | ✅ 内联无跨域问题 |
性能(首次加载) | ✅ 异步加载,不阻塞 HTML 解析 | ⚠️ 内联增加 HTML 体积,可能阻塞渲染 |
缓存能力 | ✅ 浏览器可缓存 SVG 文件 | ❌ 内联 SVG 无法单独缓存(除非模板) |
三、使用场景建议
适合用 <img>
的情况:
- SVG 是静态图标或装饰图,无需交互或动态修改。
- 希望利用浏览器缓存(如网站 logo、图标库)。
- 从 CDN 加载,希望减少主文档体积。
- 不关心 SVG 内部结构,仅作为"图片"使用。
示例:网站 Logo、社交媒体图标、装饰性插图。
适合用 <svg>
内联的情况:
- 需要动态修改颜色、大小、动画(如数据可视化、动态图表)。
- 需要绑定事件(如点击某个图形触发操作)。
- 需要高可访问性(如图标含
<title>
描述)。 - 希望用 CSS 控制样式(如主题切换时改变 SVG 颜色)。
- SVG 含文本内容,希望被搜索引擎索引。
示例:交互式图表、动态图标按钮、可访问性要求高的 UI 元素。
四、进阶技巧
1. 使用 <use>
标签复用内联 SVG
html
<svg style="display: none;"> <symbol id="icon-home" viewBox="0 0 24 24"> <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/> </symbol> </svg> <!-- 多次复用 --> <svg><use href="#icon-home"></use></svg> <svg><use href="#icon-home"></use></svg>
既保留内联 SVG 的控制力,又实现复用和缓存友好。
2. 使用 CSS Filter 修改 <img>
中 SVG 颜色(有限)
css
img.svg {
filter: invert(50%) sepia(100%) hue-rotate(180deg);
}
不精确,仅视觉效果,不改变实际 fill/stroke。
五、调试小贴士
- 在 DevTools 中,
<img>
里的 SVG 不会展开内部结构。 <svg>
内联元素可像普通 DOM 一样审查、修改、打断点。- 可通过
getSVGDocument()
(已废弃/受限)尝试访问<img>
内 SVG,但现代浏览器基本不支持。
总结一句话:
用 <img>
当"图片",用 <svg>
当"组件"。 选择哪种方式,取决于你是否需要"控制 SVG 内部" ------ 如果需要,必须内联;如果只是展示,<img>
更轻量高效。