SVG 优化:在不损失质量的情况下减小文件大小
· 12分钟阅读
目录
理解 SVG 优化
可缩放矢量图形(SVG)是一种图像格式,与 JPG 或 PNG 等传统光栅图像有着根本性的不同。SVG 利用基于 XML 的矢量数据来显示图形,使其能够无限缩放而不损失质量。这使它们非常适合响应式网页设计、高分辨率显示器以及需要在任何尺寸下保持图像清晰度的应用程序。
尽管具有固有优势,但当 SVG 从 Adobe Illustrator、Figma、Sketch 或 Inkscape 等设计工具导出时,它们通常携带不必要的数据,导致文件大小膨胀。这些多余数据包括编辑器特定的元数据、冗余属性、过于精确的坐标以及在生产环境中毫无用处的结构性低效问题。
优化 SVG 对于减小文件大小至关重要,可以确保更快的网页加载时间,同时保持视觉质量。一个优化良好的 SVG 可以比未优化的版本小 40-80%,直接影响首次内容绘制(FCP)和最大内容绘制(LCP)等页面性能指标。
专业提示:对于使用较慢连接的移动用户来说,每一千字节都很重要。将 50KB 的 SVG 优化到 15KB 可能意味着流畅体验和令人沮丧的等待之间的差别。
SVG 文件的结构
在深入研究优化技术之前,了解 SVG 文件的组成至关重要。SVG 文件本质上是具有特定结构的 XML 文档,浏览器可以解释并将其呈现为图形。
核心 SVG 组件
典型的 SVG 文件包含几个关键元素:
- 根 SVG 元素:定义视口和坐标系统
- 形状元素:构成视觉内容的路径、圆形、矩形、多边形和线条
- 分组元素:
<g>标签,用于组织相关形状 - 定义:
<defs>部分,包含可重用元素,如渐变、图案和滤镜 - 样式信息:内联样式、CSS 类或表现属性
- 元数据:关于文件创建、作者和编辑历史的信息
为什么 SVG 会变得臃肿
设计工具优先考虑可编辑性和兼容性,而不是文件大小。当您导出 SVG 时,这些工具通常包括:
- 坐标的完整小数精度(例如,123.456789 而不是 123.46)
- 浏览器已经假定的默认值
- 空组和未使用的定义
- 编辑器特定的命名空间和元数据
- 可以合并的内联样式
- 用于人类可读性的注释和空白
了解这些组件可以帮助您在优化过程中就删除什么和保留什么做出明智的决定。
适合删除的元素
并非所有 SVG 内容都是同等重要的。许多元素在设计阶段发挥作用,但在生产中成为累赘。以下是您可以安全删除的内容的全面分类。
不必要的元数据
许多设计工具插入的元数据在网页上呈现 SVG 时并不需要。诸如 sodipodi: 或 inkscape: 之类的标签通常表示 Inkscape 特定的编辑器元数据。同样,Illustrator 添加的 xmlns:x 和 xmlns:i 命名空间会被浏览器忽略。
要删除的常见元数据元素包括:
- 包含 RDF 或 Dublin Core 信息的
<metadata>标签 - 根 SVG 元素中的编辑器特定命名空间
- Illustrator 导出的
data-name属性 - Sketch 文件中的
sketch:type属性
删除这些标签不会影响图形的外观,但在某些情况下可以将文件大小减少 10-20%。
过时的注释
虽然像 <!-- 示例注释 --> 这样的注释在开发或设计过程中对记录 SVG 很有用,但它们对最终产品来说并非必需。解释图层名称、设计决策或版本信息的注释会增加字节数,但不会为最终用户增加价值。
删除这些注释是减小文件大小的简单方法,特别是在具有大量文档的复杂 SVG 中。
隐藏的图层和元素
有时,用于编辑目的的图层或元素保持隐藏状态,但仍然是导出文件的一部分。查找具有 display:none、visibility:hidden 或 opacity:0 属性的元素并删除这些隐藏元素。
如果您的 SVG 源自多层设计,这种仔细检查可以显著减小文件大小。隐藏元素可能包括:
- 用于对齐的参考图层
- 替代设计版本
- 注释图层
- 禁用的效果或滤镜
快速提示:在删除隐藏元素之前,请验证它们是否未被应用程序中的 JavaScript 或 CSS 切换。某些交互式 SVG 故意包含隐藏元素用于动画目的。
未使用和冗余的定义
SVG 文件通常包含遗留的定义,如未使用的渐变、滤镜、图案和剪切路径。这些定义位于 <defs> 部分,但从未被任何可见元素引用。
发现并删除这些未使用的定义可以显著减小文件大小,特别是在从复杂设计文件导出的图标集或图形中。查找:
- 具有唯一 ID 但未在任何
fill或stroke属性中引用的渐变 - 创建但从未应用的滤镜
- 定义但未使用的剪切路径
- 从未使用
<use>元素实例化的符号
默认属性值
SVG 元素对许多属性都有默认值。明确声明这些默认值会浪费字节。例如:
fill="black"是不必要的,因为黑色是默认填充颜色stroke="none"可以删除,因为元素默认没有描边opacity="1"是冗余的,因为假定完全不透明fill-rule="nonzero"可以省略,因为它是默认值
删除这些显式默认值可以为每个元素节省几个字节,在复杂图形中会迅速累积。
过度的小数精度
设计工具通常以过度的小数精度导出坐标和值。像 123.456789123 这样的坐标提供了人眼无法察觉且对渲染不必要的虚假精度。
将坐标四舍五入到 2-3 位小数通常就足够了,可以在没有任何可见质量损失的情况下将文件大小减少 15-30%。123.456789 和 123.46 之间的差异小于 0.003 像素——在任何实际观看尺寸下都完全不可见。
使用 SVGO 进行优化
SVGO(SVG 优化器)是自动化 SVG 优化的行业标准工具。它是一个基于 Node.js 的工具,通过插件架构应用数十种优化技术,使其既强大又可定制。
安装和使用 SVGO
您可以根据工作流程通过几种方法使用 SVGO:
命令行安装:
npm install -g svgo
svgo input.svg -o output.svg
批量处理:
svgo -f ./input-folder -o ./output-folder
与构建工具集成:
SVGO 通过专用插件与 webpack、Gulp、Grunt 和其他构建系统无缝集成。这使您可以在构建过程中自动优化 SVG。
SVGO 配置选项
SVGO 的强大之处在于其可配置性。您可以创建一个 svgo.config.js 文件来自定义应用哪些优化:
module.exports = {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
cleanupIds: {
minify: false
}
}
}
}
]
}
您应该了解的关键插件:
- removeDoctype:删除 XML 文档类型声明
- removeComments:从文件中删除所有注释
- cleanupAttrs:删除属性中不必要的空白
- removeMetadata:消除编辑器元数据
- removeUselessDefs:删除未使用的定义
- cleanupNumericValues:四舍五入数字以降低精度
- convertPathData:优化路径命令以获得更短的输出
- mergePaths:在可能的情况下合并多个路径
专业提示:始终在配置中保持 removeViewBox: false。viewBox 属性对于响应式 SVG 至关重要,永远不应删除,尽管 SVGO 的默认行为如此。
在线 SVGO 工具
如果您不想使用命令行工具,几个基于网页的界面提供 SVGO 优化:
- SVGOMG:SVGO 的网页 GUI,具有实时预览和可自定义设置
- ImgKit SVG 优化器:我们自己的 SVG 优化器工具,具有常见用例的预设配置
- Jake Archibald 的 SVGOMG:原始网页界面,具有并排比较功能
这些工具非常适合一次性优化,或者当您需要快速优化几个文件而无需设置构建过程时。
理解 SVGO 输出
运行 SVGO 后,您通常会看到显著的文件大小减少。以下是典型优化报告可能显示的内容:
| 指标 | 之前 | 之后 | 减少 |
|---|---|---|---|
| 文件大小 | 48.3 KB | 12.7 KB | 73.7% |
| 元素 | 342 | 298 | 12.9% |
| 属性 | 1,247 | 856 | 31.4% |
| 路径命令 | 2,891 | 2,891 | 0% |
请注意,路径命令保持不变——SVGO 优化它们的表示,但不改变实际的绘图指令,从而保持视觉保真度。
手动优化技术
虽然自动化工具处理大多数优化任务,但手动技术可以获得更好的结果,特别是对于图标和简单图形。了解这些技术还可以帮助您从一开始就创建更高效的 SVG。
简化路径
路径数据通常是 SVG 文件中最大的组成部分。在不损失视觉质量的情况下简化路径是一门艺术,结合了技术知识和视觉判断。
路径简化技术:
- 在导出前在设计工具中删除不必要的锚点
- 使用平滑曲线而不是多个小段
- 在可能的情况下将复杂形状转换为更简单的基本形状
- 合并具有相同样式的相邻路径段
例如,用路径绘制的圆可以用 <circle> 元素替换,将代码从数十个字符减少到只有几个属性。
使用相对路径命令
SVG 路径支持绝对和相对命令。相对命令(小写字母)通常产生更短的输出,因为它们使用相对于当前位置的较小数字。
比较这些等效路径:
<!-- 绝对命令 -->
<path d="M 10 10 L 100 10 L 100 100 L 10 100 Z"/>
<!-- 相对命令 -->
<path d="M 10 10 h 90 v 90 h -90 Z"/>
相对版本更短,通常更易读。SVGO 的 convertPathData 插件会自动处理这个问题,但了解这个原理有助于手动编码 SVG。
合并样式
不要在多个元素中重复内联样式,而是使用 CSS 类或父组上的表现属性来合并它们。
优化前:
<circle cx="10" cy="10" r="5" fill="#4f46e5" stroke="#000" stroke-width="2"/>
<circle cx="30" cy="10" r="5" fill="#4f46e5" stroke="#000" stroke-width="2"/>
<circle c