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

zhyaof 8年前發布 | 8K 次閱讀 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

 

 本文由用戶 zhyaof 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!