一個標籤的72變,打造一個純CSS圖標庫

每次要用到圖標的時候都會到 icono 去copypaste,但每次用到的時候尺寸都各不同,老是要調整參數,巨煩。固然你能夠會想到用zoom、scale來作縮放,可是這樣的縮放會使得線寬也變粗了,不甚滿意。css

終於下定心思來改造一個可縮放的圖標庫。github先上:https://github.com/qieguo2016/iconoo目前提供下載link標籤引入和npm+webpack的引入方式,詳見項目的readme。(喂,來個star!)。上圖:前端

關於改造,一開始的想法就是使用百分比尺寸來改造,而後立刻發現不可行了,繪製圖標最依賴的兩種手段:border、box-shadow都不能夠用百分比,因此這個想法,pass!而後很天然就想到了在單位上作文章,rem?No、No、No,一個庫依賴全局變量那簡直是個笑話。剩下的天然就是em了,在icon級設置font-size,而後icon自己以及後代都以這個font-size爲參照,Perfect!webpack

CSS繪圖的原理

使用CSS繪製線條,用到的不外乎兩個屬性:border & box-shadow。而形狀則能夠用border-radius、transform控制,位置會用到絕對定位、transform、margin等。CSS的繪圖,作過幾個就知道大概是怎麼回事了,歸根到底,仍是幾何。git

好比最簡單的加號:github

 1 .plus {
 2     box-sizing : border-box;
 3     display : inline-block;
 4     position : relative;
 5     font-size : 20px;
 6 }
 7 
 8 .plus:before, plus:after {
 9     content : '';
10     pointer-events : none;
11     position : absolute;
12     left : 50%;
13     top : 50%;
14     transform : translate(-50%, -50%);
15     box-shadow : inset 0 0 0 1em;
16 }
17 
18 .plus:before {
19     width : 1em;
20     height : 2px;
21 }
22 
23 .plus:after {
24     height : 1em;
25     width : 2px;
26 }
View Code

實現很是簡單,經過設置兩個僞類的寬高造成橫豎兩個小矩形,接着用陰影填充滿,這樣一個加號必需的圖形就出來了。而後就是調整位置了,將這兩個矩形居中,加號就出來了。具體是經過絕對定位+反向偏移的方式,巧妙利用了這兩個屬性百分比參照的不一樣實現居中。尺寸方面,全部尺寸除了線寬(2px)外都使用em這個相對單位,因此調整font-size的值就能夠調整圖標的大小了。若是要調整線寬,那就須要改變這個2px了,引入less、sass將線寬定義成變量就能夠很方便地改變線寬了。web

CSS的各類玩法

原理雖然簡單,可是不少圖標仍是至關有意思的,經過分析這些圖標也能加深對css的認識。例如:npm

這個圖形網上說的應該仍是比較多的了,第一眼看到懵逼了。。。分析一下,最外層的邊框明顯能夠用border來作,而後用個before來作圓點也很是簡單,關鍵是兩座大山要如何繪製呢?box-shadow貌似能夠作多層邊框呢,而後加個旋轉是否是就出來了呢?繪製流程以下:canvas

上CSS代碼吧:瀏覽器

 1 .icon-test {
 2     display: inline-block;
 3     position: relative;
 4     box-sizing: border-box;
 5     width: 90px;
 6     height: 80px;
 7     border: 5px solid;
 8     border-radius: 10px;
 9     color: #2ba5bb;
10     overflow: hidden;
11 }
12 
13 .icon-test:before,.icon-test:after {
14     content: '';
15     pointer-events: none;
16     position: absolute;
17 }
18 
19 .icon-test:before {
20     width: 10px;
21     height: 10px;
22     top: 18px;
23     right: 20px;
24     box-shadow: inset 0 0 0 1em;
25     border-radius: 50%;
26 }
27 
28 .icon-test:after {
29     width: 60px;
30     height: 50px;
31     left: 0;
32     bottom: -27px;
33     box-shadow: inset 0 0 0 50px,30px -20px 0 0;
34     transform: rotate(45deg);
35 }
View Code

再來一個:sass

看起來跟上一個有點像,然而,按照上一個的繪製方式卻怎麼也畫不出來~~~仍是分解幾步來畫,邊框很容易解決,一個box-shadow就完事。這兩座大山其實形狀都同樣,都是一個三角形下接一個矩形,三角形顯然能夠用border來畫,而矩形用box-shadow就能夠了!這裏還用了透明border來作左側和下側的留白,比直接用尺寸對齊要好不少。

 1 .icon-test {
 2     display: inline-block;
 3     position: relative;
 4     box-sizing: border-box;
 5     color: #2ba5bb;
 6     width: 60px;
 7     height: 40px;
 8     border-top-width: 0;
 9     border-right-width: 0;
10     border: 4px solid;
11     border-color: transparent;
12     box-shadow: -4px 5px;
13     overflow: hidden;
14 }
15 
16 .icon-test:before,.icon-test:after {
17     content: '';
18     pointer-events: none;
19     position: absolute;
20 }
21 
22 .icon-test:before {
23     left: 0;
24     bottom: 8px;
25     border: 14px solid transparent;
26     border-bottom-color: currentColor;
27     box-shadow: 0 16px;
28 }
29 
30 .icon-test:after {
31     left: 28px;
32     bottom: 9px;
33     border-width: 0 9px 21px;
34     border-style: solid;
35     border-color: transparent transparent currentColor;
36     box-shadow: 0 17px;
37 }
View Code

怎麼樣?以爲這些都是小玩意?好吧,都讓開,我要開始裝逼了!

 
 

蒙娜麗莎?什麼鬼?我會告訴你這也是一個單標籤純CSS畫出來的嗎?

幾千條box-shadow構成的蒙娜麗莎,看的我內分泌都失調了。。。

(author:Jay Salvat, 來源:http://codepen.io/jaysalvat/pen/HaqBf )

如此變態的繪圖,都沒有怎麼用到CSS中最強大的變形,若是加入變形,那能夠畫出來的形狀就更多了。。。更多CSS玩意兒,請到codepen上去探寶吧!

PS: 蒙娜麗莎這種圖形,能夠讀取原圖信息轉換成單位面積的box-shadow,前端用canvas就能夠作的,其實這貨的技術含量比一個圖片圖標還要少呢。話雖如此,複雜圖形使用CSS來繪製的話,性價比仍是過低,建議仍是使用圖片,這樣會更具表現力一些,操做起來也更加簡單!專業的繪圖仍是交給專業的UI去作吧!

大大小小的坑

其實,遇到的這些都不能叫作坑,是本身對CSS的理解度不夠而已。原覺得,將原來icono使用的單位換算成em就算完事了,然而,一改font-size就變形了,頓時懵逼!究其緣由,其實也很簡單,並非全部地方與font-size都是正比的,不少地方混入了線寬的影響,因此要剔除線寬的影響。

去除線寬影響的方法不外乎兩種:

1)去掉線寬,例如使用box-shadow等不影響尺寸的屬性

2)將線寬歸入計算內,好比translate反向偏移掉線寬,這樣總體縮放就不會受到線寬的影響了。

另一個比較煩的就是居中,其實居中基本上就只用到了下面兩種方式,仍是蠻簡單的。只是,這個反覆的copypaste,煩哪!

1. 絕對定位+margin:auto。

position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;

實現原理:利用css定位規則,設置左右、上下方向定位爲0,margin爲auto,讓css根據定位計算margin值,用hack的方式實現居中。居中塊的尺寸須要可控,由於css計算margin時也須要參考尺寸值,因爲四周爲0,因此自動計算獲得的盒子尺寸(含margin)是與父容器同樣的。不管是設置居中塊的width、height或者是max-height、max-width,都是讓尺寸不會擴大到與父級同樣。

侷限:在參考系父級(position!=static)大小比自己要小的時候,水平方向的居中就會失效。(垂直方向依然居中)

2. 絕對定位 + transform反向偏移。

position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
margin: auto; 

實現原理:先絕對定位相對父級偏移50%,而後使用transform來反向偏移。因爲transform的計算基準是元素自己,因此這裏能夠用50%來作反向偏移。

侷限:這個方案須要固定居中塊的尺寸值(不能設置max-width等範圍限制),瀏覽器須要以此爲基準來計算定位!

綜合來講,方案2的居中方式明顯會比方案1要好,可是在繪製圖標的時候會用到transform來作一些偏移,爲了避免覆蓋偏移效果因此要用到方案的方式來作居中。除了這兩種居中方式,還有inline-block對齊after/before子元素的方式,還有table和flexbox的方式來實現居中,可是畫圖標自己層級有限並且也用到了before/after,因此不適用圖標繪製。

最後一點

目前純CSS的圖標仍是挺多應用場景的,這種圖標的方案免去了作雪碧圖和維護雪碧圖的麻煩,並且減小了圖片資源的請求,從性能上來講會有那麼0.01s的提升吧。不用堆雪碧圖還方便調整顏色,性能還有0.01s的優化,這套CSS圖標你還不趕忙用起來?!

PS:各位看官以爲不錯的話,還請順手給個github星星哈。多攥幾顆星星,說不定就升職加薪贏取白富美了呢~~~

PPS:再附上幾個神級的CSS效果吧(by Fabrizio Bianchi  來源: http://codepen.io/fbrz/pen/iqtlk):

相關文章
相關標籤/搜索