> 本文出處:https://github.com/cssmagic/blog/issues/52
## 前言
> 我在第二屆 CSS Conf(2015 中國 CSS 開發者大會)上的演講廣受好評,很多網友向我索取現場視頻。條件所限,這個演講并沒有留下視頻存檔。因此,本文嘗試在靜態幻燈片的基礎上,以文字的方式還原現場講解,盡可能為不能去現場的朋友呈現最完整的體驗。
>
> 我在每幅圖片之間補充了講解文字。你不用分辨每段文字是配合上圖還是下圖的,只管順序閱讀即可。
* * *
[](https://box.kancloud.cn/2015-09-11_55f268cea522b.jpg)
大家看到封面的畫風,應該可以看出我今天走的不是技術路線,而是娛樂路線。如果說前面幾位講師的分享是燒腦的懸疑推理大片,我這個環節就是輕松愉快的爆米花電影了,大家可以放松一下。
[](https://box.kancloud.cn/2015-09-11_55f268cf3d5e8.jpg)
接下來,接照慣例,需要介紹一下 “這個人”。有兩個標簽可以描述這個人。
首先,他來自百姓網(此處省略百姓網的誘人之處一百字)。歡迎各位小伙伴到百姓網來看一看,我們一起來玩些好玩的。
第二個標簽是這個:
[](https://box.kancloud.cn/2015-09-11_55f268d54e672.jpg)
大家可能會說,“把 CSS 寫進自己的名字”,聽起來這么拽,那你上一屆 CSS Conf 怎么沒來?
[](https://box.kancloud.cn/2015-09-11_55f268d5c6824.jpg)
上一屆 CSS Conf 我確實沒有來。我給自己找的理由是北京太遠了,我就不去了。但實際上我自己很清楚,真正的原因是,我并不知道自己應該在這樣的大會上分享什么。
第二屆 CSS Conf 就在上海,我沒有任何理由不來,但我仍然需要面對這個問題——我要為現場的觀眾分享些什么呢?
其實,最近這幾年,在 CSS 領域出現了很多好東西:
[](https://box.kancloud.cn/2015-09-11_55f268d678c09.jpg)
當我聽說它們、了解它們、使用它們的時候,我的心情是這樣的——
[](https://box.kancloud.cn/2015-09-11_55f268d74f66e.jpg)
右邊的這個小男孩就是我。我的心情是激動、新奇、興奮。
那么,我會在 CSS Conf 上分享它們嗎?一番思索之后,我的答案是——“不”。
有幾個原因:首先,我相信肯定會有其它同學會分享它們;此外,它們不是 CSS,它們并不能解決我們在 CSS 上遇到的問題。
[](https://box.kancloud.cn/2015-09-11_55f268d80758d.jpg)
更重要的是,它們其實跟我沒什么關系,它們是別人寫的優秀的工具,而我只是在享受別人的發明所帶來的便利。就好像我在游樂場 high 了一天之后,我還是我,還是要回到自己平凡的生活。
那我應該分享些什么?我嘗試在記憶的長河中逆流而上,找尋 CSS 最初帶給我的欣喜和感動。
[](https://box.kancloud.cn/2015-09-11_55f268da3129c.jpg)
我發現,有一件事情,即使在今天,仍然可以實實在在地帶給我樂趣——那就是用 CSS 的各種神奇的特性,實現各種神奇的效果。有些效果甚至令人驚嘆——“這怎么可能是用 CSS 實現的?!”
[](https://box.kancloud.cn/2015-09-11_55f268daae7fa.jpg)
在?[我的個人主頁](http://www.cssmagic.net/#demo)?上,收錄了一些 CSS 謎題。所謂 “謎題”,就是需要費一番腦筋才能實現的效果。每一道題都有我自己的解答和評述。
[](https://box.kancloud.cn/2015-09-11_55f268db65b22.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_55f268dd1343b.jpg)
點擊第二和第三個,展開效果是這樣的:
[](https://box.kancloud.cn/2015-09-11_55f268dda4e9e.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)
第一部分會介紹一件 CSS 能做的有趣的事情;第二部分是我最近遇到的一件值得高興的事情。
首先,這件趣事就是用 CSS 畫圖標。
[](https://box.kancloud.cn/2015-09-11_55f268e459c94.jpg)
請問現場有哪些同學嘗試過?(僅前三排就有多人舉手。)好的,試過的同學接下來一定會找到很多共鳴。
有同學可能會問:
[](https://box.kancloud.cn/2015-09-11_55f268e4eb50f.jpg)
我這里不想找一些技術上的原因,單從感性的角度來回答這個問題。
[](https://box.kancloud.cn/2015-09-11_55f268e55fe8e.jpg)
它太好玩了!只有你試過,你才知道它有多好玩。
有一句話,大家可能聽過,是說 JS 的:
[](https://box.kancloud.cn/2015-09-11_55f268e5e13a4.jpg)
我這里借用這個句型,說一個 CSS 的版本:
[](https://box.kancloud.cn/2015-09-11_55f268eb61577.jpg)
不信?我們來看一些例子:
[](https://box.kancloud.cn/2015-09-11_55f268ebe3896.jpg)
在 CSS3 剛開始火起來的時候,大家肯定見過這張圖——用 CSS3 畫的機器貓。
[](https://box.kancloud.cn/2015-09-11_55f268f18222f.jpg)
用純 CSS 畫的 iPhone。
[](https://box.kancloud.cn/2015-09-11_55f268f239dd0.jpg)
用 CSS 畫的小黃人。
很多公司的 logo 也是很有特點的,也被網友用 CSS 畫了出來,比如 Opera 的 logo:
[](https://box.kancloud.cn/2015-09-11_55f268f2cb18a.jpg)
最神奇的是下面這個:
[](https://box.kancloud.cn/2015-09-11_55f268f35962e.jpg)
(笑聲。)
居然還有網友用 CSS3 畫了一個 IE8 的圖標。不過,諷刺的是,IE8 自己完全沒有能力正常渲染這個圖標。(笑聲。)
這件事情這么好玩,我自己當然也是做過的。
[](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)
怎樣用 CSS 來畫一個矩形?這沒有任何難度,因為任何一個塊元素本身就是矩形。
改變它的寬高,把它拉長,就可以得到一條線:
[](https://box.kancloud.cn/2015-09-11_55f268f535a7d.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_55f26900bb486.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_55f26901e053d.png)
……或者直角三角形等等。
[](https://box.kancloud.cn/2015-09-11_55f2690259c3d.png)
以上是在 CSS2 時代用 CSS 畫圖標時我們可以做的。CSS3 為 CSS 增加了更加強大的能力,我們看來一個例子:
[](https://box.kancloud.cn/2015-09-11_55f26902ad273.png)
CSS3 增加了圓角屬性,給一個矩形設置圓角,可以得到一個圓角矩形;逐漸增加圓角半徑到一定的程度,我們就可以得到一個圓形。
[](https://box.kancloud.cn/2015-09-11_55f269032b313.png)
圓角除了對邊框有效,還可以對實色矩形生效。比如這條短線,我們可以把它設置為圓頭的樣式;CSS3 還增加了旋轉這樣的變形屬性,我們可以把它扭轉一定的角度。
把這兩個圖形組合起來,我們就可以得到……
[](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_55f2690445322.png)
……和這個:
[](https://box.kancloud.cn/2015-09-11_55f26904b236b.png)
下面這個圖標稍稍有些復雜:
[](https://box.kancloud.cn/2015-09-11_55f26905117ed.png)
你可能會想,它居然也可以用 CSS 畫出來?
我們先從簡單的開始。三角形我們已經介紹過了,所以先把它隱去:
[](https://box.kancloud.cn/2015-09-11_55f269057eb3e.png)
再來看外層的那個有斜向缺口的矩形框。斜角缺口也需要利用邊框交界處的斜邊來實現,不過這個框無法用一個元素來實現,我們需要分兩步走。完成一邊:
[](https://box.kancloud.cn/2015-09-11_55f26905ec0cc.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_55f269075b66d.jpg)
這里有一個塊元素,設置了邊框和圓角,它的兩條邊框會通過一段圓弧連接起來:
[](https://box.kancloud.cn/2015-09-11_55f269080d4e0.png)
首先,第一個真相,邊框圓角可以指定兩個半徑值(下圖中的?`r1`?和?`r2`):
[](https://box.kancloud.cn/2015-09-11_55f2690d5d48a.png)
如果這兩個半徑值相等,則連接兩條邊框的圓弧就是一條相標準的 1/4 圓弧。如果不相等(比如我們把?`r2`減小),會得到這樣的效果:
[](https://box.kancloud.cn/2015-09-11_55f2690de4847.png)
我們發現連接兩條邊框的圓弧會變成一道 1/4 橢圓弧。這個真相解決了我們在尺度上的問題。接下來,我們需要解決形狀上的問題。
第二個真相,不同方向上的邊框的厚度(下圖中的?`w1`?和?`w4`)也是可以不一樣的:
[](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_55f2691427180.png)
最終,我們就實現了這個乍看起來不可能用 CSS 實現的圖標。
[](https://box.kancloud.cn/2015-09-11_55f26905117ed.png)
看到這里,可能有同學會說:
[](https://box.kancloud.cn/2015-09-11_55f26923ebffe.jpg)
“你這是奇技淫巧啊!”
事實上,我們剛剛介紹的技巧都是標準的 CSS 特性。只有那些對 CSS 的各種特性觀察入微的人,才有可能在非常規的場景之下把這些特性發揮出來,從而完成不可能完成的任務。——這是我對所謂 CSS “奇技淫巧” 的理解。
說到 CSS 圖標這件事,有一個網站不能不提。
[](https://box.kancloud.cn/2015-09-11_55f269245fc4e.jpg)
這個網站叫?[one-div.com](http://one-div.com/),收錄了這位站長制作的純 CSS 圖標。這個網站最大的特點在于,所有的圖標只用到了一個?`<div>`?標簽。(驚嘆聲。)很有創意,推薦大家觀摩。
用 CSS 畫圖標這么好玩的事情,肯定不止我和這位站長會想到。我們搜索 “純 CSS 圖標” 這個關鍵字,可以發現有很多的案例和開源項目。
[](https://box.kancloud.cn/2015-09-11_55f269250298d.jpg)
當然,我們也會聽到反對的聲音。比如這一條:
[](https://box.kancloud.cn/2015-09-11_55f26926083e2.jpg)
“用 CSS 畫圖標,這種瘋狂的事情趕快停止吧!”
大家玩得這么開心,你一本正經地來教育大家,很無趣,對吧?當然,這篇文章的觀點肯定有它的道理,但任何一門技術都是有優點和缺點的,要看使用場景。比如,下面就是一個正面的例子:
[](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_55f26927de48f.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)
同時,我還順手支持了 IE8。
[](https://box.kancloud.cn/2015-09-11_55f2692e2fa87.png)
因為 IE8 支持偽元素,我們沒有理由放棄它。只不過 IE8 無法渲染圓角,我們在 IE8 下只有方角效果了。
[](https://box.kancloud.cn/2015-09-11_55f2692e9ee3a.jpg)
好的,以上就是我的分享的第一部分——CSS 圖標。
(掌聲。)
* * *
#### 鳴謝
* 插畫作者:[小妖](http://weibo.com/u/1793462007)(百姓網設計師)