1. 程式人生 > >【CSS進階】box-shadow 與 filter:drop-shadow 詳解及奇技淫巧

【CSS進階】box-shadow 與 filter:drop-shadow 詳解及奇技淫巧

box-shadow 在前端的 CSS 編寫工作想必十分常見。但是 box-shadow 除去它的常規用法,其實還存在許多不為人知的奇技淫巧。

box-shadow 常規用法

說到 box-shadow ,首先想到的必然是它能夠生成陰影,所以稱之為 shaodow ,簡單看看它的語法:

基礎屬性語法

box-shadow 屬性向框新增一個或多個陰影。

box-shadow: h-shadow v-shadow blur spread color inset;

像這樣 box-shadow: 10px 10px 5px #888888; 除此之外,我們要知道,box-shadow 是分外 shadow 和內 shadow 的,內陰影即是在屬性上新增 inset 。

OK,本文已經假設你對 box-shadow 有了一定的瞭解,在此基礎上,我們再看看 box-shadow 有什麼其它妙用。

box-shadow 模擬多邊框

通常而言,我們會給許多元素新增邊框 border,但是當如果需要多重邊框,這個時候,由於 border 單重的限制,box-shadow 就可以閃亮登場了。我們可以輕鬆的使用外陰影或者內陰影來模擬邊框效果。

可以看到,由內至外,這裡利用 box-shadow ,設定了白色、黑色、灰色三層邊框及最外層帶模糊的陰影。

box-shadow 有一個引數是設定 blur 的,即是模糊的距離,在上面的例子中,即是第二重陰影 0 0 0 10px #333,

 中的第三個 0 ,當 blur 的值為 0 ,那麼陰影本身是不會模糊的,那麼就很容易模擬出邊框的效果。

而且,元素可以設定多重陰影,並且它們存在層疊關係,離 box-shadow 最近設定的層疊優先順序最高,依次遞減,這個對照程式碼很好理解。

當然,值得注意的是:

  • 陰影並不是邊框,它們並不佔有實際的空間,也不能歸屬於 box-sizing 的範圍。不過,你可以通過使用內邊距或外邊距(取決於陰影是內部的還是外部的)佔據額外的空間來模擬。

  • 上述示例模擬的邊框是位於元素外部的。它不能捕獲類似懸停和點選的滑鼠事件。如果事件很重要,那麼可以通過新增 inset 關鍵字讓陰影出現在元素的內部。注意,你可能需要新增額外的內邊距來擴充空間。

box-shadow 模擬半透明遮罩層

很多時候,我們需要用到類似下圖這樣的遮罩層,通過半透明遮罩層把背景調暗,凸顯某些 UI 元件,提升使用者體驗。

常規的做法通常都會用到一個額外的元素,用作遮罩層,至少也是一個偽元素, before 或者 after

不考慮低版本的相容性的話,其實用 box-shadow 也可以模擬遮罩層這種效果。

這裡還有一個例子,hover 時利用配合 scale 放大元素, box-shadow 產生遮罩,聚焦使用者關注視野。

當然,值得注意的是:

  • 使用這種方法不可避免的需要考慮相容性,IE9+、Firefox 4、Chrome、Opera 以及 Safari 5.1.1 支援 box-shadow 屬性。

  • 由於每個人的瀏覽器視口大小不一致,為了所有情況下 box-shadow 生成的陰影都能覆蓋整個頁面,可能需要將陰影的尺寸 spread 設定的很大。

  • 如果你真的想嘗試這個方法,box-shadow 從效能角度而言屬於 耗效能樣式,不同樣式在消耗效能方面是不同的,box-shadow 從渲染角度來講十分耗效能,原因就是與其他樣式相比,它們的繪製程式碼執行時間過長。雖然有 GPU 的 3D 加速,但是具體使用的時候還是值得斟酌考慮。不過你要知道,沒有不變的事情,在今天效能很差的樣式,可能明天就被優化,並且瀏覽器之間也存在差異。

下面再講講多重 box-shadow 能幹啥:

多重 box-shadow 之簡單圖形

從本質上講,box-shadow 是將自身投影到另一個地方,在很多情況下,我們是可以利用 box-shadow 來複制自身的!

利用這個特性,我們可以用 box-shadow 製作一些簡單的圖形,在我的單標籤圖形 Demo 中,有這樣一個圖形:

其中的雲層,就是利用了 多重box-shaodw 在一個偽元素內生成的。下面我利用不同的顏色,直觀的表達一下如何利用 box-shadow 繪製這個圖形:

當所有陰影的顏色都是同色的時候,就很自然變成了一朵雲朵:

當然,腦洞夠大的話,更復雜一點的也是可以的,來看看下面這個圖形,也是由單個標籤完成:

其中比較困難的是其中環繞字母 e 的那個圓以及那個切入的不規則角,看看用陰影怎麼把它做出來,利用了兩重 box-shadow:

嗯,當然,你問我這些圖形有什麼用。我覺得實用性真的不強吧,我個人而言是興趣,從中獲取到了樂趣,同時也學到了很多東西,對屬性本身印象也更加深刻,遇到許多 CSS 方面的問題的時候,思路更加開闊。

多重 box-shadow 實現立體感

這種方法運用在 text-shadow 上同樣可以,可以實現文字的立體感。

運用多重 box-shadow ,不斷偏移 1px ,就可以產生十分立體的感覺。

運用在按鈕:

運用在文字:

多重 box-shadow 實現任意圖片轉換

嗯,講真~~ 我覺得這個是最有趣的。

多重 box-shadow 還能做什麼呢。由於 box-shadow 的多重性,也就是 無論多少重都可以,那麼理論上任意一張圖片,每一個畫素點都可以由一重 1px*1px 的 box-shadow 來表示。

為了完成這個任務, canvas 剛好提供了一個方法 CanvasRenderingContext2D.getImageData 可以獲取到圖片每一個畫素點的 rgba 值,那麼圖片轉為一個完全由 box-shadow 表示的圖片是完全可行的。

為此,我倒騰了許久,寫了這麼一個小外掛,可以將任意圖片轉化為由 box-shadow 表示的單個 div 標籤。

如果上面的幾點還有用武之地,那麼這個功能我覺得除了看似厲害之外真的是毫無實用之處,上面也說了,box-shadow 是比較耗效能的,因為即便是一個 100px*100px 的圖形,轉化之後都有 10000 重陰影,無論是對效能還是可讀性而言,都是毀滅性的,但是講真,還是挺有趣的。

box-shadow 就先說這些吧,box-shadow 肯定還要其它的一些妙用,細心之人可以繼續挖掘之。

filter:drop-shadow

其實說到 box-shadow,就不得不提到另一個和它極為相似的 CSS3 新屬性 filter:drop-shadow,filter 即是 CSS 濾鏡,可以在元素呈現之前,為元素的渲染提供一些效果,如模糊、顏色轉移之類的。濾鏡常用於調整影象、背景、邊框的渲染。

當然這裡我們只說 filter:drop-shadow。

filter:drop-shadow 也很好玩,本想繼續長篇大論討論下去,無奈發現 張鑫旭大神兩篇文章已經把我想說的都囊括了,前人栽樹,後人乘涼,我也就不再獻醜了。

兩篇非常值得一讀的文章:

另外 《CSS SECRET》(CSS揭祕)這本大作也對 filter:drop-shadow 有詳細的描述,可以去看看。

希望這篇文章對大家有所幫助,尤其是在對問題解決的思維層面上。

到此本文結束,如果還有什麼疑問或者建議,可以多多交流,寫文章不容易,覺得不錯的希望大家點個推薦。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。