ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
> 本文出处:https://github.com/cssmagic/blog/issues/52 ## 前言 > 我在第二届 CSS Conf(2015 中国 CSS 开发者大会)上的演讲广受好评,很多网友向我索取现场视频。条件所限,这个演讲并没有留下视频存档。因此,本文尝试在静态幻灯片的基础上,以文字的方式还原现场讲解,尽可能为不能去现场的朋友呈现最完整的体验。 > > 我在每幅图片之间补充了讲解文字。你不用分辨每段文字是配合上图还是下图的,只管顺序阅读即可。 * * * [![重拾 CSS 的乐趣 - 幻灯片封面](https://box.kancloud.cn/2015-09-11_55f268cea522b.jpg)](https://box.kancloud.cn/2015-09-11_55f268cea522b.jpg) 大家看到封面的画风,应该可以看出我今天走的不是技术路线,而是娱乐路线。如果说前面几位讲师的分享是烧脑的悬疑推理大片,我这个环节就是轻松愉快的爆米花电影了,大家可以放松一下。 [![CSS魔法 #百姓网#](https://box.kancloud.cn/2015-09-11_55f268cf3d5e8.jpg)](https://box.kancloud.cn/2015-09-11_55f268cf3d5e8.jpg) 接下来,接照惯例,需要介绍一下 “这个人”。有两个标签可以描述这个人。 首先,他来自百姓网(此处省略百姓网的诱人之处一百字)。欢迎各位小伙伴到百姓网来看一看,我们一起来玩些好玩的。 第二个标签是这个: [![#把 CSS 写进名字的男人#](https://box.kancloud.cn/2015-09-11_55f268d54e672.jpg)](https://box.kancloud.cn/2015-09-11_55f268d54e672.jpg) 大家可能会说,“把 CSS 写进自己的名字”,听起来这么拽,那你上一届 CSS Conf 怎么没来? [![CSS Conf](https://box.kancloud.cn/2015-09-11_55f268d5c6824.jpg)](https://box.kancloud.cn/2015-09-11_55f268d5c6824.jpg) 上一届 CSS Conf 我确实没有来。我给自己找的理由是北京太远了,我就不去了。但实际上我自己很清楚,真正的原因是,我并不知道自己应该在这样的大会上分享什么。 第二届 CSS Conf 就在上海,我没有任何理由不来,但我仍然需要面对这个问题——我要为现场的观众分享些什么呢? 其实,最近这几年,在 CSS 领域出现了很多好东西: [![Sass、Stylus、Less、PostCSS 等 logo](https://box.kancloud.cn/2015-09-11_55f268d678c09.jpg)](https://box.kancloud.cn/2015-09-11_55f268d678c09.jpg) 当我听说它们、了解它们、使用它们的时候,我的心情是这样的—— [![插画:小男孩在游乐场](https://box.kancloud.cn/2015-09-11_55f268d74f66e.jpg)](https://box.kancloud.cn/2015-09-11_55f268d74f66e.jpg) 右边的这个小男孩就是我。我的心情是激动、新奇、兴奋。 那么,我会在 CSS Conf 上分享它们吗?一番思索之后,我的答案是——“不”。 有几个原因:首先,我相信肯定会有其它同学会分享它们;此外,它们不是 CSS,它们并不能解决我们在 CSS 上遇到的问题。 [![灰化的各个 logo](https://box.kancloud.cn/2015-09-11_55f268d80758d.jpg)](https://box.kancloud.cn/2015-09-11_55f268d80758d.jpg) 更重要的是,它们其实跟我没什么关系,它们是别人写的优秀的工具,而我只是在享受别人的发明所带来的便利。就好像我在游乐场 high 了一天之后,我还是我,还是要回到自己平凡的生活。 那我应该分享些什么?我尝试在记忆的长河中逆流而上,找寻 CSS 最初带给我的欣喜和感动。 [![插画:小男孩蹲在地上玩积木](https://box.kancloud.cn/2015-09-11_55f268da3129c.jpg)](https://box.kancloud.cn/2015-09-11_55f268da3129c.jpg) 我发现,有一件事情,即使在今天,仍然可以实实在在地带给我乐趣——那就是用 CSS 的各种神奇的特性,实现各种神奇的效果。有些效果甚至令人惊叹——“这怎么可能是用 CSS 实现的?!” [![CSS魔法个人主页截图 - CSS 谜题 1](https://box.kancloud.cn/2015-09-11_55f268daae7fa.jpg)](https://box.kancloud.cn/2015-09-11_55f268daae7fa.jpg) 在 [我的个人主页](http://www.cssmagic.net/#demo) 上,收录了一些 CSS 谜题。所谓 “谜题”,就是需要费一番脑筋才能实现的效果。每一道题都有我自己的解答和评述。 [![CSS魔法个人主页截图 - CSS 谜题 2](https://box.kancloud.cn/2015-09-11_55f268db65b22.jpg)](https://box.kancloud.cn/2015-09-11_55f268db65b22.jpg) 在这些谜题中,收获最多赞叹的,应该是这个案例——弧形排列的可折叠二级导航。 [![弧形排列的可折叠二级导航](https://box.kancloud.cn/2015-09-11_55f268dc1d33f.jpg)](https://box.kancloud.cn/2015-09-11_55f268dc1d33f.jpg) 这是 2009 年的时候,一位网友在论坛里求助,说他们公司的设计师想要实现这样一个效果。大家看到背景是一个弧形的造型,所有导航菜单需要顺着这个背景图案以弧形排列。 [![弧形排列的可折叠二级导航 - 红框标注](https://box.kancloud.cn/2015-09-11_55f268dc8b265.jpg)](https://box.kancloud.cn/2015-09-11_55f268dc8b265.jpg) 而且,有些菜单是可以展开的(上图中加红框的部分)。当我点击第一个可展开菜单时,效果是这样的: [![弧形排列的可折叠二级导航 - 导航展开演示 1](https://box.kancloud.cn/2015-09-11_55f268dd1343b.jpg)](https://box.kancloud.cn/2015-09-11_55f268dd1343b.jpg) 点击第二和第三个,展开效果是这样的: [![弧形排列的可折叠二级导航 - 导航展开演示 2](https://box.kancloud.cn/2015-09-11_55f268dda4e9e.jpg)](https://box.kancloud.cn/2015-09-11_55f268dda4e9e.jpg) ……和这样的: [![弧形排列的可折叠二级导航 - 导航展开演示 3](https://box.kancloud.cn/2015-09-11_55f268e3443ea.jpg)](https://box.kancloud.cn/2015-09-11_55f268e3443ea.jpg) 所有菜单项都需要顺滑地贴合这个弧形背景自然展开。 论坛里的网友纷纷表示,这样的效果应该用 Flash 来实现才对,用 CSS 怎么可能做到?! 我动了一番脑筋,[最终把这个效果做了出来](http://www.cssmagic.net/demo/20090215-arc-nav/)。当然,在这个例子里,我用到了一些 JS,用来监听点击事件、切换元素 class;除此以外所有的元素布局和定位都是由 CSS 来完成的,也就是说,你可以任意地改变菜单项的数量和内容。 大家可以试试,在 2009 年,要兼容 IE6,应该怎么做? 今天由于时间关系,我们不会讲解这个案例。我会跟大家聊一些跟 CSS 有关的趣事。我今天的分享分为两个部分: [![幻灯片大纲:一件趣事、一件乐事](https://box.kancloud.cn/2015-09-11_55f268e3b2257.jpg)](https://box.kancloud.cn/2015-09-11_55f268e3b2257.jpg) 第一部分会介绍一件 CSS 能做的有趣的事情;第二部分是我最近遇到的一件值得高兴的事情。 首先,这件趣事就是用 CSS 画图标。 [![CSS 图标](https://box.kancloud.cn/2015-09-11_55f268e459c94.jpg)](https://box.kancloud.cn/2015-09-11_55f268e459c94.jpg) 请问现场有哪些同学尝试过?(仅前三排就有多人举手。)好的,试过的同学接下来一定会找到很多共鸣。 有同学可能会问: [![为什么要用 CSS 画图标?](https://box.kancloud.cn/2015-09-11_55f268e4eb50f.jpg)](https://box.kancloud.cn/2015-09-11_55f268e4eb50f.jpg) 我这里不想找一些技术上的原因,单从感性的角度来回答这个问题。 [![为什么要用 CSS 画图标? - 好玩!](https://box.kancloud.cn/2015-09-11_55f268e55fe8e.jpg)](https://box.kancloud.cn/2015-09-11_55f268e55fe8e.jpg) 它太好玩了!只有你试过,你才知道它有多好玩。 有一句话,大家可能听过,是说 JS 的: [![“所有可以用 JS 写的项目,最终一定会用 JS 重写一遍”](https://box.kancloud.cn/2015-09-11_55f268e5e13a4.jpg)](https://box.kancloud.cn/2015-09-11_55f268e5e13a4.jpg) 我这里借用这个句型,说一个 CSS 的版本: [![“所有可以用 CSS 画出来的图形,最终一定会用 CSS 再画一遍”](https://box.kancloud.cn/2015-09-11_55f268eb61577.jpg)](https://box.kancloud.cn/2015-09-11_55f268eb61577.jpg) 不信?我们来看一些例子: [![机器猫](https://box.kancloud.cn/2015-09-11_55f268ebe3896.jpg)](https://box.kancloud.cn/2015-09-11_55f268ebe3896.jpg) 在 CSS3 刚开始火起来的时候,大家肯定见过这张图——用 CSS3 画的机器猫。 [![iPhone 3GS](https://box.kancloud.cn/2015-09-11_55f268f18222f.jpg)](https://box.kancloud.cn/2015-09-11_55f268f18222f.jpg) 用纯 CSS 画的 iPhone。 [![小黄人](https://box.kancloud.cn/2015-09-11_55f268f239dd0.jpg)](https://box.kancloud.cn/2015-09-11_55f268f239dd0.jpg) 用 CSS 画的小黄人。 很多公司的 logo 也是很有特点的,也被网友用 CSS 画了出来,比如 Opera 的 logo: [![Opera logo](https://box.kancloud.cn/2015-09-11_55f268f2cb18a.jpg)](https://box.kancloud.cn/2015-09-11_55f268f2cb18a.jpg) 最神奇的是下面这个: [![IE8 logo](https://box.kancloud.cn/2015-09-11_55f268f35962e.jpg)](https://box.kancloud.cn/2015-09-11_55f268f35962e.jpg) (笑声。) 居然还有网友用 CSS3 画了一个 IE8 的图标。不过,讽刺的是,IE8 自己完全没有能力正常渲染这个图标。(笑声。) 这件事情这么好玩,我自己当然也是做过的。 [![CMUI demo 页面截图](https://box.kancloud.cn/2015-09-11_55f268f425ea4.jpg)](https://box.kancloud.cn/2015-09-11_55f268f425ea4.jpg) 我写过一个移动端的 Web UI 框架叫 [CMUI](https://github.com/CMUI/CMUI),在最初的版本中,[图标的解决方案](http://cmui.net/demo/v0/html/element/icon.html) 就是用纯 CSS 来实现的。 我们来看一下用 CSS 画图标会用到哪些基本原理。 [![黑色矩形](https://box.kancloud.cn/2015-09-11_55f268f4d17e6.png)](https://box.kancloud.cn/2015-09-11_55f268f4d17e6.png) 怎样用 CSS 来画一个矩形?这没有任何难度,因为任何一个块元素本身就是矩形。 改变它的宽高,把它拉长,就可以得到一条线: [![黑色水平线](https://box.kancloud.cn/2015-09-11_55f268f535a7d.png)](https://box.kancloud.cn/2015-09-11_55f268f535a7d.png) 那怎样得到一个三角形? [![黑色三角形](https://box.kancloud.cn/2015-09-11_55f2690000478.png)](https://box.kancloud.cn/2015-09-11_55f2690000478.png) 在早期的 CSS 中,没有任何特性是跟斜线直接相关的。但你要相信劳动人民的智慧是无穷的。很快 CSS 开发者们就发现了关于边框的一个秘密。 [![黑色方框](https://box.kancloud.cn/2015-09-11_55f269006da43.png)](https://box.kancloud.cn/2015-09-11_55f269006da43.png) 这是一个加了边框的块元素。当我们把四个方向上的边框设置为不同的颜色时,效果会变成这样: [![四边为彩色边框的矩形](https://box.kancloud.cn/2015-09-11_55f26900bb486.png)](https://box.kancloud.cn/2015-09-11_55f26900bb486.png) 我们会发现,在不同边框颜色的交界处,出现了一道斜边。接下来,我们逐渐减小这个元素的宽高至零,同时增加各条边框的厚度,最终会变成这个样子: [![四个彩色三角形拼合的矩形](https://box.kancloud.cn/2015-09-11_55f26901202c8.png)](https://box.kancloud.cn/2015-09-11_55f26901202c8.png) 我们会得到四个头对头的三角形! 接下来,我们用透明色把不需要的三条边框隐去,就可以得到一个三角形: [![绿色三角形](https://box.kancloud.cn/2015-09-11_55f269016e4e5.png)](https://box.kancloud.cn/2015-09-11_55f269016e4e5.png) 通过改变这个元素各条边框的厚度,就可以改变这个三角形各条边的角度。我们可以得到锐角三角形: [![绿色三角形 - 顶角为锐角](https://box.kancloud.cn/2015-09-11_55f26901e053d.png)](https://box.kancloud.cn/2015-09-11_55f26901e053d.png) ……或者直角三角形等等。 [![绿色三角形 - 某个角为直角](https://box.kancloud.cn/2015-09-11_55f2690259c3d.png)](https://box.kancloud.cn/2015-09-11_55f2690259c3d.png) 以上是在 CSS2 时代用 CSS 画图标时我们可以做的。CSS3 为 CSS 增加了更加强大的能力,我们看来一个例子: [![方框、圆角框、圆形](https://box.kancloud.cn/2015-09-11_55f26902ad273.png)](https://box.kancloud.cn/2015-09-11_55f26902ad273.png) CSS3 增加了圆角属性,给一个矩形设置圆角,可以得到一个圆角矩形;逐渐增加圆角半径到一定的程度,我们就可以得到一个圆形。 [![线段、圆头线段、斜 45° 的圆头线段](https://box.kancloud.cn/2015-09-11_55f269032b313.png)](https://box.kancloud.cn/2015-09-11_55f269032b313.png) 圆角除了对边框有效,还可以对实色矩形生效。比如这条短线,我们可以把它设置为圆头的样式;CSS3 还增加了旋转这样的变形属性,我们可以把它扭转一定的角度。 把这两个图形组合起来,我们就可以得到…… [![放大镜图标](https://box.kancloud.cn/2015-09-11_55f26903792bd.png)](https://box.kancloud.cn/2015-09-11_55f26903792bd.png) 一个放大镜的图标。 根据这个思路,常见的图形都可以拆解开来,化整为零,用 CSS 画出来。比如下面这个: [![加号](https://box.kancloud.cn/2015-09-11_55f26903e5f2d.png)](https://box.kancloud.cn/2015-09-11_55f26903e5f2d.png) ……这个: [![房子](https://box.kancloud.cn/2015-09-11_55f2690445322.png)](https://box.kancloud.cn/2015-09-11_55f2690445322.png) ……和这个: [![卡通小人半身像](https://box.kancloud.cn/2015-09-11_55f26904b236b.png)](https://box.kancloud.cn/2015-09-11_55f26904b236b.png) 下面这个图标稍稍有些复杂: [![iOS 6 的动作图标](https://box.kancloud.cn/2015-09-11_55f26905117ed.png)](https://box.kancloud.cn/2015-09-11_55f26905117ed.png) 你可能会想,它居然也可以用 CSS 画出来? 我们先从简单的开始。三角形我们已经介绍过了,所以先把它隐去: [![iOS 6 的动作图标 - 隐去三角形](https://box.kancloud.cn/2015-09-11_55f269057eb3e.png)](https://box.kancloud.cn/2015-09-11_55f269057eb3e.png) 再来看外层的那个有斜向缺口的矩形框。斜角缺口也需要利用边框交界处的斜边来实现,不过这个框无法用一个元素来实现,我们需要分两步走。完成一边: [![iOS 6 的动作图标 - 隐去部分外框](https://box.kancloud.cn/2015-09-11_55f26905ec0cc.png)](https://box.kancloud.cn/2015-09-11_55f26905ec0cc.png) ……再完成一边: [![iOS 6 的动作图标 - 隐去外框](https://box.kancloud.cn/2015-09-11_55f2690640aa8.png)](https://box.kancloud.cn/2015-09-11_55f2690640aa8.png) 最后我们剩下的难题似乎就是这个奇怪的形状了,好像是个鹰嘴的样子。 [![类似鹰嘴的图形](https://box.kancloud.cn/2015-09-11_55f269068eee8.png)](https://box.kancloud.cn/2015-09-11_55f269068eee8.png) 这个形状如何实现?给大家五秒钟的时间考虑一下。 在揭开谜底之前,我们需要了解一下: [![关于圆角的两个真相](https://box.kancloud.cn/2015-09-11_55f269075b66d.jpg)](https://box.kancloud.cn/2015-09-11_55f269075b66d.jpg) 这里有一个块元素,设置了边框和圆角,它的两条边框会通过一段圆弧连接起来: [![边框和圆角](https://box.kancloud.cn/2015-09-11_55f269080d4e0.png)](https://box.kancloud.cn/2015-09-11_55f269080d4e0.png) 首先,第一个真相,边框圆角可以指定两个半径值(下图中的 `r1` 和 `r2`): [![边框和圆角 - 标示圆角的半径](https://box.kancloud.cn/2015-09-11_55f2690d5d48a.png)](https://box.kancloud.cn/2015-09-11_55f2690d5d48a.png) 如果这两个半径值相等,则连接两条边框的圆弧就是一条相标准的 1/4 圆弧。如果不相等(比如我们把 `r2`减小),会得到这样的效果: [![边框和椭圆圆角](https://box.kancloud.cn/2015-09-11_55f2690de4847.png)](https://box.kancloud.cn/2015-09-11_55f2690de4847.png) 我们发现连接两条边框的圆弧会变成一道 1/4 椭圆弧。这个真相解决了我们在尺度上的问题。接下来,我们需要解决形状上的问题。 第二个真相,不同方向上的边框的厚度(下图中的 `w1` 和 `w4`)也是可以不一样的: [![边框和圆角 - 标示边框的厚度](https://box.kancloud.cn/2015-09-11_55f2690e3e9b3.png)](https://box.kancloud.cn/2015-09-11_55f2690e3e9b3.png) 如果我们逐渐减小 `w4` 的值至零,我们会得到这个形状: [![类似鹰嘴的图形,末端延长](https://box.kancloud.cn/2015-09-11_55f26913adbfa.png)](https://box.kancloud.cn/2015-09-11_55f26913adbfa.png) 大家应该可以看出,我们需要的形状已经出现了。最后,我们调整一下这个元素的宽高,只保留我们需要的部分,就可以得到这个鹰嘴的形状。 [![类似鹰嘴的图形](https://box.kancloud.cn/2015-09-11_55f2691427180.png)](https://box.kancloud.cn/2015-09-11_55f2691427180.png) 最终,我们就实现了这个乍看起来不可能用 CSS 实现的图标。 [![iOS 6 的动作图标](https://box.kancloud.cn/2015-09-11_55f26905117ed.png)](https://box.kancloud.cn/2015-09-11_55f26905117ed.png) 看到这里,可能有同学会说: [![“奇技淫巧”?](https://box.kancloud.cn/2015-09-11_55f26923ebffe.jpg)](https://box.kancloud.cn/2015-09-11_55f26923ebffe.jpg) “你这是奇技淫巧啊!” 事实上,我们刚刚介绍的技巧都是标准的 CSS 特性。只有那些对 CSS 的各种特性观察入微的人,才有可能在非常规的场景之下把这些特性发挥出来,从而完成不可能完成的任务。——这是我对所谓 CSS “奇技淫巧” 的理解。 说到 CSS 图标这件事,有一个网站不能不提。 [![one-div.com 网页截图](https://box.kancloud.cn/2015-09-11_55f269245fc4e.jpg)](https://box.kancloud.cn/2015-09-11_55f269245fc4e.jpg) 这个网站叫 [one-div.com](http://one-div.com/),收录了这位站长制作的纯 CSS 图标。这个网站最大的特点在于,所有的图标只用到了一个 `<div>` 标签。(惊叹声。)很有创意,推荐大家观摩。 用 CSS 画图标这么好玩的事情,肯定不止我和这位站长会想到。我们搜索 “纯 CSS 图标” 这个关键字,可以发现有很多的案例和开源项目。 [![Google 搜索结果截图 1](https://box.kancloud.cn/2015-09-11_55f269250298d.jpg)](https://box.kancloud.cn/2015-09-11_55f269250298d.jpg) 当然,我们也会听到反对的声音。比如这一条: [![Google 搜索结果截图 2](https://box.kancloud.cn/2015-09-11_55f26926083e2.jpg)](https://box.kancloud.cn/2015-09-11_55f26926083e2.jpg) “用 CSS 画图标,这种疯狂的事情赶快停止吧!” 大家玩得这么开心,你一本正经地来教育大家,很无趣,对吧?当然,这篇文章的观点肯定有它的道理,但任何一门技术都是有优点和缺点的,要看使用场景。比如,下面就是一个正面的例子: [![fileicon.css 项目主页截图](https://box.kancloud.cn/2015-09-11_55f269267fa16.jpg)](https://box.kancloud.cn/2015-09-11_55f269267fa16.jpg) 这是一个开源项目,叫 [fileicon.css](https://github.com/picturepan2/fileicon.css),作者是中国人。 为什么说它是一个正面的例子呢?因为,作为一个样式库,它的接口非常清晰。 [![代码](https://box.kancloud.cn/2015-09-11_55f269278ffad.png)](https://box.kancloud.cn/2015-09-11_55f269278ffad.png) 你只需要使用一个空元素,再加上一些有意义的属性就可以了。 然后,你就可以得到一个设计精致的文件图标了——它有着优雅的圆角,还有一个可爱的折角效果。 [![文件图标](https://box.kancloud.cn/2015-09-11_55f26927de48f.png)](https://box.kancloud.cn/2015-09-11_55f26927de48f.png) 我很喜欢这个项目。 不过在现有的版本中,它有一个小缺憾——只能把它放在纯白的背景上。如果你把它放在其它背景上,会发现它的折角的空缺位置是不透明的: [![文件图标与透明背景](https://box.kancloud.cn/2015-09-11_55f2692838b2b.png)](https://box.kancloud.cn/2015-09-11_55f2692838b2b.png) 实际上能做到这一步已经很不容易了。大家可以自己试一下,用一个空标签把这样的图标做出来。 我很喜欢这个项目,于是我花了一点时间,给作者写了一个 [demo](https://github.com/picturepan2/fileicon.css/issues/2#issuecomment-128747900)。我用了一些 CSS 奇技淫巧,把折角处做成了真正的透明: [![文件图标与透明背景](https://box.kancloud.cn/2015-09-11_55f26928d4b1e.png)](https://box.kancloud.cn/2015-09-11_55f26928d4b1e.png) 同时,我还顺手支持了 IE8。 [![文件图标与透明背景](https://box.kancloud.cn/2015-09-11_55f2692e2fa87.png)](https://box.kancloud.cn/2015-09-11_55f2692e2fa87.png) 因为 IE8 支持伪元素,我们没有理由放弃它。只不过 IE8 无法渲染圆角,我们在 IE8 下只有方角效果了。 [![笑脸](https://box.kancloud.cn/2015-09-11_55f2692e9ee3a.jpg)](https://box.kancloud.cn/2015-09-11_55f2692e9ee3a.jpg) 好的,以上就是我的分享的第一部分——CSS 图标。 (掌声。) * * * #### 鸣谢 * 插画作者:[小妖](http://weibo.com/u/1793462007)(百姓网设计师)