CSS 精灵图指南 - 创建和优化图像精灵表

· 9 分钟阅读

什么是 CSS 精灵图 - 将多张图像合并为一张

CSS 精灵图将多个小图像 (图标、按钮、装饰元素) 合并到一张大图中,通过 CSS background-position 显示特定区域。这减少了 HTTP 请求数量,在 HTTP/1.1 时代是重要的性能优化手段。

名称的由来:精灵图 (sprite) 一词来自游戏开发中的「精灵表」。从任天堂红白机、超级任天堂的时代起,把角色的各个动画帧集中放在一张图上就是标准做法,Web 开发沿用了这个概念和名称。

工作原理:元素设置固定宽高,背景图为精灵表,通过负的 background-position 值将目标图标移动到可见区域。

历史背景: HTTP/1.1 下浏览器对同一域名的并发连接数有限 (通常 6 个),大量小图像会导致请求排队。假设页面上有 30 个图标,单独加载就需要 30 次请求;合并为精灵表后只需 1 次。精灵图将数十个请求合并为一个,显著提升加载速度。

现代意义:随着 HTTP/2 和 HTTP/3 的普及,多路复用 (multiplexing) 减少了合并请求的必要性,但精灵图在特定场景 (游戏、大量图标) 仍有价值。具体收益有三点:一是省去每个文件各自的开销 (请求头、TLS 握手);二是浏览器缓存的命中效率更高,一个文件的缓存策略比几十个文件更容易管理;三是合并后的总体积往往小于各文件之和 —— 图标集这类色调和尺寸相近的图像,放在一张图里压缩时冗余更容易被消除,压缩率的提升尤其明显。此外还能减少 DNS 查询和连接建立的开销。

精灵表设计原则 - 高效布局策略

精灵表的布局直接影响文件大小和使用便利性。如果毫无规划地排列图像,CSS 会变得冗长难读,日后追加或替换图标也会很痛苦。

布局策略:

  • 网格布局:所有图标统一尺寸,等间距排列。坐标计算简单 (偏移量都是 -Npx -Mpx 这样的规则值),可维护性最高,适合 16x16px、24x24px、32x32px 等统一规格的图标集
  • 紧凑布局:不同尺寸的图标紧密排列,最小化空白。通常借助装箱 (bin packing) 算法把整张图压到最小。文件更小但坐标复杂,实际上必须配合自动生成工具使用
  • 分类布局:按功能分组 (导航图标一行,社交图标一行)。便于维护,也能避免让只在某个页面用到的图标被所有页面加载

间距设计:设计上的要点是确保余白 (padding)。

  • 图标间留 1-2px 间距防止相邻图标渗透 (子像素渲染)。特别是用 background-size 缩放时,没有间距会让相邻图标的边缘露进来
  • 为 Retina 屏幕准备 2 倍尺寸的精灵表并缩小显示时,建议把间距放大到 2-4px
  • 过大间距浪费空间,过小可能出现边缘伪影

尺寸考虑:

  • 精灵表总尺寸控制在 2048x2048 以内 (移动设备限制)
  • 宽度为 2 的幂次有助于 GPU 纹理处理
  • 考虑 Retina 屏幕:提供 2x 版本

为扩展留出余地:在图的右侧或底部预留一块空白,日后追加图标时就不必改动既有图标的坐标,CSS 的改动量能降到最低。

精灵表创建 - 工具与工作流

精灵表的制作分为用图像编辑软件手工排版和用工具自动生成两种。根据项目规模和图标的更新频率来选择。

构建工具集成 (推荐):

  • webpack-spritesmith: Webpack 插件,自动从图标目录生成精灵表和 CSS/SCSS。支持 HMR (Hot Module Replacement),开发中新增图标会自动重建精灵表
  • gulp.spritesmith: Gulp 任务,监听文件变化自动重建。spritesmith 本身是 Node.js 的精灵图生成库,只要把图片放进指定目录,就会同时产出精灵表和配套的 CSS/SCSS
  • postcss-sprites: PostCSS 插件,自动将 CSS 中引用的小图合并。由于不需要改写既有的 background-image 声明,把它引入到遗留项目里很容易

命令行工具:

  • spritesheet-js: Node.js 工具,支持多种布局算法
  • ImageMagick montage: montage icon*.png -geometry +2+2 sprite.png

在线工具:

  • SpritePad:拖拽式在线精灵表生成器
  • CSS Sprite Generator:上传图像自动生成

手工制作 (小规模项目):在 Figma 或 Photoshop 里建立画板,沿网格摆放图标,导出时根据内容选择 PNG-8 (256 色以内的图标) 或 PNG-24 (含渐变的图标)。坐标需要手写进 CSS,因此图标超过 20 个就该转向自动生成工具。

输出格式:工具通常同时生成精灵表图像和 CSS/SCSS/JSON 坐标文件。坐标文件记录每个图标的位置和尺寸。

SVG 精灵 (现代的替代手段):矢量格式的图标适合用 SVG 精灵。以 <symbol> 元素定义各个图标、用 <use> 元素引用。与 CSS 精灵不同,颜色和尺寸都能用 CSS 自由改变,也不需要单独适配 Retina。可以用 svg-spritesvgo 等工具自动生成。

CSS 实现技巧 - 掌握 background-position

正确使用 CSS 属性显示精灵图中的特定图标。基本思路是:用一个公共类指定精灵表,再用各自的类指定坐标和尺寸。

基本用法:

.icon {
display: inline-block;
width: 24px;
height: 24px;
background-image: url('sprites.png');
background-repeat: no-repeat;
}
.icon-home { background-position: 0 0; }
.icon-search { background-position: -24px 0; }
.icon-user { background-position: -48px 0; }

Retina 适配:准备 2 倍 (或 3 倍) 尺寸的图,再用 background-size 缩小显示。例如要让 24x24px 的图标适配 Retina,就用 48x48px 绘制精灵表,并指定 background-size: 原始图宽的一半 auto;

.icon {
background-image: url('sprite@2x.png');
background-size: 200px 100px; /* 原始尺寸的一半 */
}

SCSS/Sass 的效率化:把坐标管理抽象成变量和 mixin,可维护性会大幅提升。常见做法是用 $icon-home: 0px 0px 24px 24px; 这样的变量记录坐标与尺寸,再由 mixin 展开。spritesmith 也支持直接生成 SCSS 模板。

@mixin sprite($x, $y, $w, $h) {
width: $w;
height: $h;
background-position: -$x -$y;
}

悬停与激活状态:把常态和悬停态的图标放进同一张精灵表,用 :hover 伪类切换 background-position。这样悬停时不需要再去加载新图像,可以避免首次悬停时的闪烁 (FOUC)。

精灵图优化 - 减小文件大小提升速度

仅仅做出精灵表还不够。要真正拿到性能收益,还需要在文件大小和显示速度上继续优化。

格式选择:

  • PNG-8:图标颜色少于 256 色时,比 PNG-24 小 60-80%。透明只能表达为 1 bit (全透明或全不透明)
  • PNG-24/32:含渐变或半透明的图标使用。文件更大,但能保住画质
  • WebP:支持透明,比 PNG 小 25-30%。浏览器支持率已超过 97%,可以积极采用,但仍需用 <picture> 或 CSS 的 image-set() 准备回退
  • SVG 精灵:矢量图标的最佳选择,无限缩放

压缩优化:

  • pngquant:有损 PNG 压缩,视觉差异极小。pngquant --quality=65-80 sprites.png 减色后,再用 optipng -o7 sprites.png 二次优化,两者组合通常能减掉 40-70%
  • oxipng:无损 PNG 优化
  • 减少颜色数:图标通常不需要完整的 24 位色彩

减少空白:

  • 使用紧凑布局算法最小化图标间空白
  • 裁剪图标周围的透明边距。图的右端或底部留有大片空白时,整张图的体积会被白白撑大
  • 考虑将不同尺寸的图标分组到不同的精灵表
  • 但如果是为了日后追加图标而有意留白,就跳过这一步

缓存策略:在文件名里加入哈希 (sprites.a3f2b1.png),就能一边设置长期缓存 (1 年),一边保证更新后必定分发新文件。Webpack 的 [contenthash] 和 Vite 的资源哈希都能做到这一点。

CSS 精灵图的现状与替代方案 - 2026 年的正确选择

CSS 精灵图在 2010 年代前期达到鼎盛,在现代 Web 开发中其必要性已大幅降低,但在特定场景仍有价值。

现代替代方案:

  • SVG 图标系统:使用 <symbol> + <use> 的 SVG 精灵,写作 <svg><use href="#icon-name"></use></svg>。矢量、可着色、可动画,不依赖分辨率所以无需 Retina 版本。在无障碍方面也更容易用 aria-label<title> 赋予语义
  • 图标字体: Font Awesome、Material Icons 等,用 colorfont-size 就能改样式,很省事。但存在屏幕阅读器误读、子像素渲染发虚、无法表达多色图标等制约,新项目正逐渐被 SVG 取代
  • 内联 SVG:直接在 HTML 中嵌入 SVG。最灵活但增加 HTML 大小
  • CSS 图标:纯 CSS 绘制简单图标。无额外请求

HTTP/2 下直接分发独立文件:多路复用让大量小文件也能高效分发,直接提供独立的 PNG/SVG 已不再像 HTTP/1.1 时代那样吃亏。不过文件数超过 100,或特别看重首次访问的性能时,精灵图和打包依然有效。

仍适合使用精灵图的场景:

  • 大量位图图标 (非矢量),比如照片风格的图标和复杂插画
  • 游戏和动画 (帧动画精灵表),以及地图应用这类基于瓦片的显示
  • 需要支持极老浏览器 (IE 11) 的项目
  • 图标数量极多 (100+) 且为位图格式
  • 既有精灵表已稳定运行,迁移成本不划算

决策建议:截至 2026 年,新项目应把 SVG 精灵作为第一选择,只在确实需要位图时才考虑 CSS 精灵图;简单图标考虑纯 CSS 实现。HTTP/2 环境下,少量独立小文件的性能损失已可忽略。

相关文章

响应式图像实现指南 - srcset、sizes 与 picture 元素完全指南

响应式图像的完整实现指南。涵盖 srcset 属性、sizes 属性、picture 元素的艺术指导及构建流程中的自动化生成。

Web 图像文件大小优化策略 - 在保持质量的同时减小体积

系统讲解 Web 图像文件大小优化技术。涵盖格式选择、分辨率优化、元数据清理、CDN 分发优化和自动化质量管理。

精灵图动画实现 - CSS 和 JavaScript 的高效帧控制

详解精灵图动画的实现方法,从 CSS steps() 函数到 JavaScript requestAnimationFrame,涵盖创建工具和性能优化。

Favicon 创建完全指南 - ICO、SVG 和 PNG 详解

了解 Favicon 的工作原理、ICO/SVG/PNG 格式的特点、暗色模式支持以及现代 Favicon 实现的浏览器兼容性。

使用 Data URI 嵌入图像 - Base64 编码原理与最佳实践

了解 Data URI 方案如何将图像直接嵌入 HTML/CSS。深入理解 Base64 编码原理、性能影响、适用场景以及何时应避免使用内联图像。

矢量图 vs 位图 - 选择正确图像格式的指南

矢量图与位图的本质区别、各自特点及最佳使用场景。涵盖 Web 开发中的实现方式及格式间的转换方法。

相关术语