一步步打造本身的純CSS單標籤圖標庫

圖標做爲網頁設計中的一部分,其在凸顯網頁重要元素特性,視覺交互、引導以及網頁裝飾等充當的角色做用舉足輕重。因爲圖標廣泛具備尺寸小的特色,在項目實踐時不宜將每一個圖標做爲單個圖片元素進行加載,這會增長Http請求,影響網頁的性能。所以,在實際中,咱們可能見到如下一些常見的解決方案:css

  • 將多個圖標按照必定排列順序合併在一個圖片裏(即sprite圖),再經過CSS設置元素的background-position來爲元素設置背景從而展現圖標
  • 將單個圖標元素轉成base64格式,並在CSS聲明背景
  • 使用SVG來繪製圖標
  • 使用字體圖標
  • 使用CSS來繪製圖標
  • ...

以上方式均可以很好的實現功能,各有各的優缺點。在移動端的某些狀況下,我我的比較偏好使用CSS來實現一些簡單的小圖標,緣由有如下幾點:html

  • 適應性和定製性強,如能夠隨意改變顏色,大小
  • 佔用空間小
  • 在移動端兼容性高
  • 能夠不斷使本身熟悉CSS3的各個屬性並得以應用

而因爲CSS3的普及和在各大瀏覽器的不斷加強支持,使CSS具備更大的可能性和能力去繪製更多樣化,更復雜的圖標。固然,也有很多人反對web圖標使用CSS繪製的,在這裏不加以討論。若是你也反對,不妨以當樂趣的心態去看待。css3

本文將單獨講解如何用CSS繪製一些圖標。而因爲用CSS實現圖標繪製,偶爾意味着你須要用更復雜的html結構去支持圖標的繪製,因此本文講解的將是單標籤CSS圖標。這樣能夠實現相似僅用img標籤或者單個標籤應用字體庫實現圖標繪製的效果。講解如何繪製以前,先給你們看看前陣子得閒繪製的若干個單標籤CSS圖標。git

你須要掌握的CSS屬性

繪製圖標,單從繪製來說,無非就是畫點、線、面。而後將多個點線面組合獲得圖標。所以,你至少應該掌握如下CSS屬性的應用github

  • 盒子模型
  • border屬性的應用(很重要,能夠參考)
  • position的各個屬性值的應用
  • transform變形
  • outline,box-shadow(常見於多邊框繪製)
  • CSS漸變(經常使用於圖標中透明過渡)
  • 類和僞元素的應用
  • transitionanimation(若是要繪製動態圖標,本文僅講解靜態圖標)

須要掌握的主要爲以上內容,有些特殊的處理可能還須要其餘一些CSS屬性的應用。web

幾個說明

  • 因爲大部分狀況下圖標的大小按照所處環境上下文的字體大小來決定,因此本文全部例子的大小單位大部分使用em,按照當前字號來設定大小
  • 有些border屬性沒有指明border-color,如border-top: .4em solid,是由於border-color默認繼承了字體顏色
  • 全部圖標僅做爲例子展現,實現方法多樣,不表明最佳實踐
  • CSS圖標不適合在實踐中大量使用,你能夠以看成樂趣和練習CSS屬性應用的心態去看待本文

基本元素的繪製

border屬性繪製元素

border除了做爲簡單的繪製邊框之外,還能夠繪製三角形,梯形,星形等任意的多邊形,如下爲繪製的兩個三角形和梯形,更多的應用能夠參考
《border屬性的多方位應用和實現自適應三角形》這篇文章,裏面全面詳細的介紹了用border繪製各類多邊形。瀏覽器

<div class="triangle1"></div>
<div class="triangle2"></div>
<div class="trapezoid"></div>複製代碼
.triangle1 {/*銳角三角形*/
    width: 0;
    height: 0;
    border-top:50px solid transparent;
    border-bottom:100px solid #249ff1;
    border-left: 30px solid transparent;
    border-right: 100px solid transparent;
}
.triangle2 {/*直角三角形*/
    width: 0;
    height: 0;
    border-top: 80px solid transparent;
    border-bottom: 80px solid #ff5b01;
    border-left: 50px solid #ff5b01;
    border-right:50px solid transparent;
    }
.trapezoid {/*梯形*/
    width:0;
    height:0;
    border-top:none;
    border-right:80px solid transparent;
    border-bottom:60px solid #13dbed;
    border-left: 80px solid #13dbed;
}複製代碼

border-radius繪製元素

border-radius主要用於繪製圓點、圓形、橢圓、圓角矩形等形狀,如下爲簡單繪製的兩個圖形。wordpress

<div class="circle"></div>
<div class="ellipse"><div>複製代碼
.circle,.ellipse {
    width: 100px;
    height: 100px;
    background: #249ff1;
    border-radius: 50%;
}
.ellipse {
    width: 150px;
    background: #ff9e01;
}複製代碼

border-radius屬性實際上能夠設置最多8個值,經過改變8個值能夠獲得許多意想不到的圖像,如圖(該圖來源於這裏post

更多關於border-radius屬性的特色和應用請參考張鑫旭大神寫的《秋月什麼時候了,CSS3 border-radius知多少?》性能

box-shadow繪製元素

對於box-shadow,其完整的聲明爲box-shadow: h-shadow v-shadow blur spread color inset,各個值表示的意義分別爲:水平方向的偏移,垂直方向的偏移,模糊的距離(羽化值),陰影的擴展大小(不設置或爲0時陰影大小與主體的大小一致),陰影的顏色和是否使用內陰影。實際應用時能夠接收3-6個值,對應分別以下:

  • 3個值: h-shadow v-shadow color
  • 4個值: h-shadow v-shadow blur color
  • 5個值: h-shadow v-shadow blur spread color
  • 6個值: h-shadow v-shadow blur spread color inset

同時,border-shadow接受由多個以上各類值組成的以逗號分隔的值,經過這一特性,咱們能夠實現如多重邊框的等效果。如下咱們用該屬性來實現一個單標籤且不借助僞元素的添加圖標表明目標的的圖標。(爲方便觀察,這裏將添加符號的實現部分用紅色代替)

<div class="plus"></div>
<div class="target"></div>複製代碼
.plus {
    width: 30px;
    height: 30px;
    margin-left: 50px;/*因爲box-shadow不佔空間,經常須要添加margin來校訂位置*/
    background: #000;
    box-shadow: 0 -30px 0 red, 
                0 30px 0 red,
                -30px 0 0 red, 
                30px 0 0 red;
}
.target {
    width: 30px;
    height: 30px;
    background: red;
    border-radius: 50%;
    margin-left: 50px;
    box-shadow: 0 0 0 10px #fff,
                0 0 0 20px red, 
                0 0 0 30px #fff,
                0 0 0 40px red;
}複製代碼

結果以下:

以上,添加符號採用多個由四個值組成的以逗號分隔的值來設置加號的四個角達到效果,目標圖標則經過屢次設置陰影大小大於主體大小的值疊加成了多個圓環來實現。

因爲box-shadow不佔據空間,實際應用中經常須要設置margin來矯正圖標的位置,這和outline屬性一致,兩個屬性最大的不一樣是outline造成的區域不會由於border-radius而造成圓角。

使用CSS漸變來繪製圖標

CSS3的漸變屬性十分強大,理論上經過漸變能夠繪製出任何的圖形,漸變的特性和使用足足能夠寫一篇長文,如下爲一個例子

<div class="gradient"></div>複製代碼
.gradient {
    position: relative;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background-color: silver;
    background-image: linear-gradient(335deg, #b00 23px, transparent 23px),
                      linear-gradient(155deg, #d00 23px, transparent 23px),
                      linear-gradient(335deg, #b00 23px, transparent 23px),
                      linear-gradient(155deg, #d00 23px, transparent 23px);
    background-size: 58px 58px;
    background-position: 0px 2px, 4px 35px, 29px 31px, 34px 6px;
}複製代碼

以上將獲得以下結果

關於線性漸變屬性的用法,能夠參考這裏

更多牛逼的例子能夠觀摩《CSS SECRETS》做者繪製的漸變背景點擊這裏

小試牛刀

有了以上的基礎以後,咱們就能夠一步步打造一個屬於本身的單標籤CSS圖標庫。文章最前面提到了下面這些圖標

如今抽取其中幾個嘗試繪製實現一下。

  • 杯子

首先咱們對杯子進行拆分,很容易想到將杯子拆分爲杯身和杯柄兩個部分。拆分以後,應該用兩個圓角矩形來實現,至於杯子的輪廓(圖中黑色部分),咱們能夠選擇用邊框border來實現,border的顏色按實際填充便可(本文未指定時默認爲跟隨當前字體的顏色)。因爲是單標籤實現,所以,咱們還要藉助一個僞元素(杯柄)來實現這個圖標。因而就有了如下的樣式:

.cup {
    display: inline-block;
    width: .9em;
    height: .4em;
    border: .25em solid;
    border-bottom: 1.1em solid;
    border-radius: 0 0 .25em .25em;
}
cup:before {
    position: absolute;
    right: -.6em;
    top: 0;
    width: .3em;
    height: .8em;
    border: .25em solid;
    border-left: none;
    border-radius: 0 .25em .25em 0;
    content: '';
}複製代碼

以上便實現了一個杯子的圖標,經過調整邊框顏色(默認爲與當前字體顏色相同)和寬度便可實現不一樣大小的圖標。

  • 心形

仔細觀察這個心形,它實際上應該能夠近似看作是由如下兩個形狀按照必定的角度旋轉和平移組成。

所以咱們能夠用兩個元素來繪製這兩個部分,經過設置背景色和border-radius,而後按照必定的角度旋轉並平移則可獲得。爲了方便定位,這裏咱們用兩個僞元素來繪製這兩個部分。爲了方便觀察,咱們先設置以下樣式

.heart{
    display: inline-block;
    margin-top: 1.5em;
    width:50px;
    height: 50px;
    background: green;
}
.heart:before,.heart:after {
  position: absolute;
  width: 1em;
  height: 1.6em;
  background: #000;
  border-radius: 50% 50% 0 0;
  content: '';
  bottom: 0;
}
.heart:before {
  -webkit-transform: rotate(45deg);
  -webkit-transform-origin: 100% 100%;
  right: 0;
  background: red;
  opacity: .5;
  z-index: 5;
}
.:after {
  -webkit-transform: rotate(-45deg);
  -webkit-transform-origin: 0 100%;
  left: 0;
  opacity: .8;
}複製代碼

能夠看到,此時兩個元素將由於.heart元素的寬度而撐開了一段距離,實際上應該是A點和B點重合於一點。所以,若是咱們把.heart的寬高都設爲0,則獲得以下結果:

到這裏爲止,已經完成了一個心形的繪製,可是仔細看,左右兩側會有一個邊角突出,這是由於旋轉的角度不夠致使。能夠經過調大角度或者設置一個較大的圓角(適應性更高)來修復此問題。這裏將旋轉的角度調整爲48deg。修改顏色和透明度後即獲得以下結果:

  • 相機

至於這個相機,因爲前面已經介紹瞭如何用border-radius繪製一個表明目標的圖標,問題就變得很簡單了。整個相機分爲三個部分,經過定位便可實現。如下直接貼實現代碼。

.camera {
    display: inline-block;
    border-style: solid;
    border-width: .65em .9em;
    border-radius: .1em;
}
.camera:before {
    position: absolute;
    top: -.3em;
    left: -.3em;
    width: .4em;
    height: .4em;
    border-radius: 50%;
    border: .1em solid #FFF;
    box-shadow: 0 0 0 .08em,0 0 0 .16em #fff;
    content: '';
}
.camera:after {
    position: absolute;
    top: -.5em;
    left: .5em;
    width: .2em;
    border-top: .125em solid #FFF;
    content: '';
}複製代碼
  • 月亮

月亮這個圖標乍一看彷佛挺難實現,但若是掌握了border-radius屬性的應用,實際上是至關的容易,如下爲完整的CSS樣式:

.moon {
    display:inline-block;
    height: 1.5em;
    width: 1.5em;
    box-shadow: inset -.4em 0 0;
    border-radius: 2em;
    transform: rotate(20deg);
}複製代碼

其核心是將陰影的模式設置爲inset經過調整參數,能夠獲得不一樣的月亮形狀,以下圖:

總結

用CSS繪製圖標其實其核心就是將拆分後的多個元素通過旋轉和平移獲得。歸根結底仍是要掌握CSS相關屬性的應用。通常由如下幾個步驟:

  • 分析圖標,拆分爲小元素
  • 繪製小元素
  • 定位(平移和旋轉等)
  • 設置在父級元素的定位(如用margin定位)

若是不限制於單個標籤實現,那麼能夠繪製更多複雜的圖標。如下爲我的在繪製圖標時的一點小體會:

  • 圖標的顏色可使用border屬性去繪製
  • border-color大部分狀況下能夠不設置,默認跟隨圖標當前所在文本的字體顏色
  • 圖標的大小單位可使用em,即相對於當前所在文本的字體大小進行計算,這應該符合與大部分場合,適應性也高,複用性強。(以上例子中均僅須要調整父級的字體大小便可以放大或縮小圖標)

相關閱讀

CSS魔法之重拾CSS樂趣(上)

CSS魔法之重拾CSS樂趣(下)

CSS3 Patterns Gallery

相關文章
相關標籤/搜索