一個標簽的72變,打造一個純CSS圖標庫
每次要用到圖標的時候都會到 icono 去copypaste,但每次用到的時候尺寸都各不一樣,總是要調整參數,巨煩。當然你可以會想到用zoom、scale來做縮放,但是這樣的縮放會使得線寬也變粗了,不甚滿意。
終于下定心思來改造一個可縮放的圖標庫。 目前提供下載link標簽引入和npm+webpack的引入方式,詳見項目的readme。
關于改造,一開始的想法就是使用百分比尺寸來改造,然后馬上發現不可行了,繪制圖標最依賴的兩種手段:border、box-shadow都不可以用百分比,所以這個想法,pass! 然后很自然就想到了在單位上做文章,rem?No、No、No,一個庫依賴全局變量那簡直是個笑話。剩下的自然就是em了,在icon級設置font-size,然后icon本身以及后代都以這個font-size為參照,Perfect!
CSS繪圖的原理
使用CSS繪制線條,用到的不外乎兩個屬性:border & box-shadow。而形狀則可以用border-radius、transform控制,位置會用到絕對定位、transform、margin等。CSS的繪圖,做過幾個就知道大概是怎么回事了,歸根到底,還是幾何。
比如最簡單的加號:
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將線寬定義成變量就可以很方便地改變線寬了。
CSS的各種玩法
原理雖然簡單,但是很多圖標還是相當有意思的,通過分析這些圖標也能加深對css的認識。例如:
這個圖形網上說的應該還是比較多的了,第一眼看到懵逼了。。。分析一下,最外層的邊框明顯可以用border來做,然后用個before來做圓點也非常簡單,關鍵是兩座大山要如何繪制呢?box-shadow貌似可以做多層邊框呢,然后加個旋轉是不是就出來了呢?繪制流程如下:
上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
再來一個:
看起來跟上一個有點像,然而,按照上一個的繪制方式卻怎么也畫不出來~~~還是分解幾步來畫,邊框很容易解決,一個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構成的蒙娜麗莎,看的我內分泌都失調了。。。
如此變態的繪圖,都沒有怎么用到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圖標你還不趕緊用起來?!
來自:http://www.cnblogs.com/qieguo/p/5999630.html