前一段時間在某專案中用到了「高斯模糊」的濾鏡效果,過程中嘗試了多種方案,這裡總結一種方式,希望可以幫助到有需要的道友~
UI 小姐姐非要讓我在 Android 系統自定義的 Webview 上支援實現我們俗稱的「毛玻璃」效果,說是一定要實現,不實現這種效果就失去了設計的靈魂,奈何我百般解釋,她就要,就要,要!
沒辦法,研究一下子咯!
【推薦學習:】
毛玻璃效果在 iOS 系統上比較常見,比如訊息通知欄、手機助手卡片等地方,所以咱開啟蘋果官網看看!
果不其然,導航欄就用到了「家族式設計」的「毛玻璃」特效
開啟控制檯抄一抄作業:
主要是用到了 backdrop-filter
CSS3 的屬性,於是乎,順手就用上了。
主要的卡片 CSS 程式碼如下:
.card-backdrop-filter { position: relative; z-index: 1; width: 600px; height: 300px; border-radius: 6px; padding: 10px; color: #fff; font-size: 16px; overflow: hidden; margin: 100px auto; backdrop-filter: blur(10px); background-color: rgba(255,255,255,0.72); }
在 Chrome 瀏覽器看著效果還可以:
然後再到某臺老 Android 版本的行動端上看看,結果不行了!!!
去查了查相容性:backdrop-filter -- caiuse
emmm~,再考慮到我司自己魔改的 Webview 核心情況。。。
需要再尋求另外的方式,這裡補充一下子,filter 可以理解為濾鏡,backdrop-filter
就是給背景設定濾鏡效果,CSS 目前支援的濾鏡效果有
blur(): 模糊 brightness(): 亮度 contrast(): 對比度 drop-shadow(): 陰影 grayscale(): 灰度 hue-rotate(): 色相旋轉 invert(): 反色 opacity(): 透明度 saturate(): 飽和度 sepia(): 褐色
如果不考慮相容性,backdrop-filter
會在不支援的瀏覽器上直接顯示背景色,也就是失去設定的效果(「體驗降級」)。
如果 UI 小姐姐和 PM 大哥能同意的話,也是非常推薦大家使用,畢竟誰不想早下班學習吶?
另一個設定模糊度的 CSS 屬性就是 filter
,那麼我們的另一個思路就是通過 filter
來模擬 backdrop-filter
屬性的效果。
且 filter
的相容性會更好:filter -- caiuse
我們看看 filter
和 backdrop-filter
效果的差異:
/* filter 的寫法,將 backdrop-filter 屬性替換為 filter */ .card-filter { position: relative; z-index: 1; width: 600px; height: 300px; border-radius: 6px; padding: 10px; color: #fff; font-size: 16px; overflow: hidden; /* 隱藏超出元素區域外的內容 */ margin: 100px auto; filter: blur(10px); background-color: rgba(255,255,255,0.72); }
這效果和實際的設計需求大相徑庭,因此還需要改改!
因為 filter
設定的是整個元素的模糊度,而不是做用於元素的背景容器,所以需要一個和卡片等大小的佔位元素來單獨設定模糊度,並作為背景元素。
3.1 ::before + 固定雙背景圖
這裡偷個懶,直接使用了偽元素 ::before
,實際場景為了考慮相容性,建議大家還是用 div
塊級元素佔位
.card-filter::before { content: ' '; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; /* 放到當前 card-filter 元素的底部 */ filter: blur(10px); /* 模糊度 */ background: url(http://p2.qhimg.com/bdr/__85/t01781bd4b1218329e1.jpg) no-repeat center fixed; background-size: cover; }
這裡注意到,卡片採用了和整個容器的背景圖屬性是一樣的,通過 fixed
方式固定背景圖,這樣當元素在任意方向捲動的時候,背景圖不會移動,能保證背景效果是一致的
3.2 利用 margin 屬性的負值擴大容器
模糊度的效果如下圖,還是有差異,因為 filter
是從容器外邊框向內聚合的一個濾鏡,導致濾鏡外邊框有一個白圈
此時只需要擴大 ::before
元素的容器大小,這裡直接可使用 margin
屬性負值擴大容器
.card-filter::before { ... + margin: -20px; }
此時的效果就有點「那個意思了」,看來快可以交差了
3.3 ::after 填補消失的背景色
原本設定在 .card-filter
類上的 background-color: rgba(255, 255, 255, 0.72);
沒起作用!
因為 ::before
偽類作用於 .card-filter
元素內,是其子元素,又因為 ::before
的 background
屬性設定了背景圖,遮蓋了父元素 .card-filter
的背景色。
知道了原因,那麼我們就可以在 .card-filter
元素內再新增一個子元素(偽類),用於設定背景色!
再偷個懶,直接使用 ::after
偽類,就不用改造 DOM 結構。
.card-filter::after { content: ' '; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; background-color: rgba(255, 255, 255, 0.72); }
此時,效果就和 backdrop-filter
的效果相同:
放到「自研」的 Webview 核心中也能看到效果了!
總的來說,如果能說服產品經理和 UI 小姐姐的話,咱就用 backdrop-filter
,說服不了就用 filter
的組合拳模擬吧!
另外 backdrop-filter
屬性是有效能問題的,咱就是說,都 2022 年了,求求大家升級一下手上的裝置吧!,相容性真讓前端工程師禿頭兒!
如果「毛玻璃」和背景沒有文中的相對移動,直接讓 UI 小姐姐切個圖,直接解決一切相容性 & 效能問題!
在研究過程中,筆者還嘗試過 SVG 的 feGaussianBlur
標籤,效果和 filter
一樣,會稍微複雜一些,不過也是個可施行的方案,大家可自行嘗試下~
原文地址:https://juejin.cn/post/7070325873202692104
(學習視訊分享:)
以上就是聊聊使用CSS怎麼實現毛玻璃特效(相容方案探究)的詳細內容,更多請關注TW511.COM其它相關文章!