CSS Sprites(精灵图)和实际应用

大众点评

前言

今天我跟朋友去吃好吃的汉堡,就是这家,棒棒的~,当我想复制名字发给他的时候,我呆了…为什么,复制不全…一查 html,这特么是啥???一看 css 我就明白了……原来精灵图反爬…,但是这个就过分了啊,影响实际体验了啊。
PS:随后我打开一看,现在已经变成自定义字体防爬……这种攻防战其实挺没意思的…

精灵图历史

精灵图起源于街机游戏,当时的意思是独立于背景的独立移动的二维图被称为 Sprite,那时候的游戏还没有 GPU 来渲染,而是通过电路,显像管等硬件在显示器逐行扫描实现的,所以这些跟背景分离的图像就跟浮起来一样,所以叫精灵(Sprite)。这个概念影响之后许多游戏引擎和整个前端行业,比如 Flash 也有 Sprite 的概念,之后游戏发展的成熟的,每一个精灵图可能都有自己动画,在之后被前端工程师节省 I/O 开销的目的集合图片在一张大图上,配合显示不同位置的图片实现一次请求多次显示。

createjs
createjs Demo 游戏的精灵图

用法

首先我们得制作出一个类似这样的图,主要在 css 实现是依靠background-position来做的,就是改变不同的定位配合长宽就可以做到。

手动制作

精灵图制作自己来最方便的就是直接搜索 css sprites generator…在线一大堆,弄完还能给你生成 css 代码,方便至极。
当然如果自己会 PhotoShop 对于一个前端工程师来讲是极好的。

自动生成

我们写代码为了什么,为了避免重复工作,既然这样如果我们能用自动绝对不用手动,如果自动可以选择前端构建工具 gulp 或者 webpack,webpack 可以使用 webpack-spritesmith 进行配置,一次配置以后都不用烦了~

使用

我来用淘宝举例子,淘宝这一块集合了精灵图和工程组件化的概念,每一个分区使用精灵图只关乎本身自己的区域,做的非常好。
我们可以看到旅行的这个模块上有两个很重要 css,一个是指向精灵图为背景,一个是精灵图定位,就可以实现这一整个模块都使用一张图,减少 I/O 开销,在这种巨无霸站里面优化和工程化平衡做的非常好!~

1
2
3
4
5
6
7
.tbh-conve .conve-item-2 .tbh-icon {
background-position: 0 -87px;
}
.tbh-icon {
background: url(https://img.alicdn.com/tfs/TB1eiXTXlTH8KJjy0FiXXcRsXXa-24-595.png)
0 0 no-repeat;
}

taobao-sprites

帧动画

平时谈起 CSS 精灵图更多的是想到减少 I/O 开销,但是在另一个领域游戏,他现在基本就是做动画,让对象动起来~,举个 🌰,这是京东和玩具总动员的一个活动页面,里面绝大多技术都是 CSS 动画,其中一进页面的就有电视在播放动画,你以为是视频?其实不仅仅这个不是,里面几乎所有都不是,全是精灵图帧动画。

通过animation控制帧的时机,来实现,这种技术在很多活动页都有用上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 这是我之前模仿这个页面写的
.anim {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(../images/tv-frames@2x_e7d7fd7d.png) 0 0 no-repeat;
background-size: 70rem 56.5rem;
animation: tv-play 6s step-start infinite both;
}

@keyframes tv-play {
0% {
background-position: 0 0;
}

1.36986% {
background-position: calc(-7rem * 1) 0;
}

2.73973% {
background-position: calc(-7rem * 2) 0;
}
// ....很有很多
}

jd-tv

总结

精灵图使用不难,减少体积减少 I/O 开销等是目的可能现在来讲没有那么重要了,条件允许还能开http2改善,如果没有多颜色要求用icoffont更方便,不过性能要求极致的大厂们依然在用,大众点评这种反爬虫也可以用。