第六课:一张大图,装下所有小图标
这是第 6 课的作业。课上讲的「雪碧图(sprite,也叫精灵图)」当时听起来很玄,
其实就是把很多小图标拼成一张大图,再靠 background-position 把背景挪来挪去,
让每个元素只露出自己要的那一格。
原作业只有三个空白方块、连一个字说明都没有,看上去完全不知道在演示什么。 这一版把坐标抽成了变量、补上了推导过程,并做成「常态 / 悬停」并排对照。
一、这张图长什么样
素材是一张 440 × 440 的正方形图,按 4 × 4 的网格排布, 实际放了 14 个图标(末尾有两格是空的)。 本页只用到其中 6 个(3 组图标 × 常态 / 悬停两个状态)。
common/music126.png)。
同一个图案有实心版和描边版,而且两者是交错排列的、
并不是按行分开:第 1 行第 4 格、第 2 行第 3 格、第 3 行第 1、2 格就是描边版。
这正是雪碧图最经典的用法:把「常态」和「按下 / 选中态」放在同一张图里,
切换时只要改一下 background-position,不用再请求第二张图片。
整张图 440px 宽、4 列 → 每行每格的步进
--cell: 110px。每格里图标的内容其实只有 90 × 90,四周各留了 10px 空白;窗口开成
--icon: 100px,坐标再让出 --gap: 5px,
图标就正好居中、四周各剩 5px 干净留白。于是取第 c 列第 r 格的公式是:
x = -(gap + c × cell),y = -(gap + r × cell)→ 第 0 / 1 / 2 列分别是
-5px、-115px、-225px。⚠️ 别写成
-(c × (cell + gap)):那样第 0 格算出 0(少偏 5px)、
第 2 格算出 -230px(多偏 5px),只有第 1 格碰巧是对的。
二、坐标速查
-
角色(人 + 音符)
常态:第 2 列第 2 行 →
-225px -225px(描边版)
悬停:第 0 列第 0 行 →-5px -5px(实心版) -
字母 A(字体 / 文字)
常态:第 0 列第 1 行 →
-5px -115px(描边版)
悬停:第 1 列第 0 行 →-115px -5px(实心版) -
盾牌(防御 / 安全)
常态:第 1 列第 1 行 →
-115px -115px(描边版)
悬停:第 2 列第 0 行 →-225px -5px(实心版)
三、常态 / 悬停对照演示
左边是常态,把鼠标移上去它会切到悬停态;右边直接把悬停后的样子并排摆出来,
方便对照——两态只差一个坐标,切换过程配了 0.2s 的过渡。
角色 / 攻击:同一个「人 + 音符」图案的两套画法。常态用描边版显得轻, 悬停换成实心版立刻变重——这就是最省事的交互反馈,用户一碰就知道「这个能点」。
字母 A / 文字:注意这两格的横坐标差了 110px,
正好是一格的距离——因为在图里它们就是左右相邻的两个格子。
盾牌 / 防御:换成实心版后颜色变重、对比更强,适合表达「已开启防护」这类确认状态。
1)方块那层浅蓝底色是故意留的:图标内容只有 90 × 90,而窗口是 100 × 100, 所以四周会露出一圈底——它正好把「取景窗口」的边界画了出来。原作业在这里写的是
background-color: pink,圆形图标的四个角会直接透出粉色,看起来像脏点;
底色不是不能用,是要挑一个看起来是有意为之的颜色。2)没有
transition 的时候,坐标是「啪」一下跳过去的;
加上 transition: background-position .2s,两态之间才有了过渡。
四、小结
雪碧图的核心就一句话:元素不换图,只换背景的位置。
它的好处是省请求(16 个图标只下 1 张图),代价是坐标全靠手算、图一改就全体错位,
所以现在更常见的是 SVG 图标或字体图标。但把这套坐标推导清楚,
对理解 background-position 的百分比、负值规则特别有帮助——
后面学 object-fit、雪碧动画(steps() 逐帧)时,
用的还是同一套思路。