CSS 图像精灵
Optional Advanced 刚讲完 !important——罕见的覆盖旗帜。本课是另一项可选主题:图像精灵(image sprites)。你会在旧样式表和一些 legacy 图标集里见到它们。想法很简单:一张图文件,多枚图标;用 background-position 决定小窗口里露出哪一块。
直接回答
CSS 图像精灵是一张把多枚图标(或按钮状态)并排放在一起的图集。每个 UI 元素拿到固定的宽高、同一张 background-image,再用 background-position 滑动图集,直到目标块填满盒子。当年每枚图标都是一次 HTTP 请求时,精灵能减少请求数。新项目通常更宜用 SVG 图标、内联 SVG 或小型图标体系——只有在维护现有图集、或必须对齐 legacy 设计时,才继续用精灵。
精灵为何出现
多年前,每枚图标往往意味着又一次 HTTP 往返。把二十张小 PNG 合成一张图集,就是一次下载、一条缓存。浏览器再用 CSS 在图集上画出不同「窗口」。HTTP/2 与现代打包减轻了这种痛,可缩放的矢量图标通常也更清晰——但当你打开旧 CSS 时,定位这一套仍是有用的素养。
三块零件
你需要:
- 一张图集 — 例如按行或网格排布的
icons.png - 一个盒子 —
width与height对齐单块(常用display: inline-block或块级链接) - 一个偏移 —
background-position,让正确的块落在盒子下
background-repeat: no-repeat防止图集平铺。你不是为每枚图标另载文件,而是用位置裁切。
共享图集上的第一块
设想每枚图标 32×32 像素,第一枚在左上。元素盒子也是 32×32,背景从 0 0 开始:
.icon {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: 0 0;
}
盒子像视口。只有 icons.png 左上 32×32 可见。图集其余部分仍在——只是被元素尺寸裁掉了。
第二枚图标:滑动图集
若下一枚从图集右移 32px 处开始,就把背景向左移 32px(负 X)。同一张图、同样盒尺寸,不同窗口:
.icon-home {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: 0 0;
}
.icon-search {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: -32px 0;
}
负 X 把图集往左拉,第二块填满窗口。第二行图标还会改 Y(例如 -32px -32px)。按真实图集测量——不要凭记忆猜偏移。
用另一块做 hover
按钮集常把默认与 hover(或 active)状态放在同一张图上。在 :hover 上只改 background-position:
.btn-icon {
display: inline-block;
width: 40px;
height: 40px;
background-image: url("btn-sheet.png");
background-repeat: no-repeat;
background-position: 0 0;
}
.btn-icon:hover {
background-position: -40px 0;
}
没有第二张图文件——只是另一次裁切。保持盒子尺寸稳定,控件才不会跳动。
平静的图集习惯
始终把图集与明确的盒子和 no-repeat 配对。类名按角色命名,而不是只写像素算术:
.sprite {
display: inline-block;
background-image: url("icons.png");
background-repeat: no-repeat;
}
.sprite--mail {
width: 24px;
height: 24px;
background-position: 0 -48px;
}
.sprite--bell {
width: 24px;
height: 24px;
background-position: -24px -48px;
}
在简短注释里记录块网格(块尺寸、行顺序),免得下一位维护者去反推魔法数字。
昔日精灵与今日图标
📊 Sprite sheets vs modern icon approaches
| Approach | Best when | Watch out |
|---|---|---|
| CSS image sprite (PNG sheet) | Legacy UI you must keep; one cached sheet already in the project | Raster scales poorly; offsets break if the sheet changes |
| Inline SVG / SVG sprite | Crisp UI icons at any size; easy theming with currentColor |
Slightly more markup or build setup |
| Icon font | Very old stacks that already ship one | Accessibility and ligature quirks; harder to theme than SVG |
| Separate PNG per icon | Rare one-off graphics | Many requests on old HTTP/1 connections |
Real <img> photos |
Content images, galleries, product shots | Not a job for background-position sprites |
图像画廊与响应式图像课使用真正的 <img>(flex 缩略图、object-fit、srcset)。精灵通常是背景里的装饰性 UI 铬件——不能替代带有意义 alt 的内容照片。
新 UI 优先现代图标
全新界面请从 SVG 起步(内联或小型 SVG 精灵系统)。边缘更锐、换色更简单,也没有脆弱的像素偏移。只有设计包本身已是图集、或你在修补依赖该图集的 CSS 时,再找经典 PNG 精灵。
/* Content photo — use <img>, not a sprite crop */
.hero-photo {
max-width: 100%;
height: auto;
}
/* UI chrome — sprite OK only if the sheet already exists */
.toolbar .icon-save {
width: 16px;
height: 16px;
background-image: url("legacy-toolbar.png");
background-repeat: no-repeat;
background-position: -64px 0;
}
自己动手试
- 在纸上画一行三枚图标(或打开真实精灵)。记下块宽(如 32px)。
- 建
.icon-a,设background-position: 0 0与匹配盒子。 - 加
.icon-b,用-32px 0(或你图集的真实第二偏移)。 - 写一条 hover 规则,移到第三块且不改宽高。
- 在注释里写一句:这张图集为何仍存在(legacy),或下次为何改用 SVG。
常见错误
- 把内容照片放进精灵,丢掉合适的
alt/ 语义 - 忘记 width 与 height,整张图集露出来或裁切不干净
- 本该反向滑动图集却用了正偏移
- 留下
background-repeat,块在盒子里重复 - 新应用默认用 PNG 精灵,而不是 SVG
- 从教程抄偏移,却没测量你自己的图集
小结
- 精灵是一张图集;
background-position决定哪一块填满固定盒子 - 历史上它减少了许多小图标的 HTTP 请求
- 保持
no-repeat、稳定尺寸与角色命名;记录网格 - 新 UI 优先 SVG(或类似方案);精灵留给 legacy 图集
- 内容图仍用真正的
<img>——画廊与响应式图像是另一回事 - Optional Advanced 下一课:多列(
multi-column)
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部