傻傻分不清楚?深入探討 Filter 與Backdrop-filter 的異同
本文將深入探討在 CSS 中兩個非常類似的屬性 -- filter 和 backdrop-filter。它們都能完成某些濾鏡功能,但是它們肯定也存在差異。那么,為什么在 CSS 中有了 filter 還誕生了 backdrop-filter 了?
帶著這個疑問,開始今天的正文。
filter VS backdrop-filter
在 CSS 中,有兩個和濾鏡相關(guān)的屬性 -- filter 和 backdrop-filter。
backdrop-filter[1] 是更為新的規(guī)范推出的新屬性,可以點擊查看 Filter Effects Module Level 2。
- filter:該屬性將模糊或顏色偏移等圖形效果應(yīng)用于元素。
- backdrop-filter:該屬性可以讓你為一個元素后面區(qū)域添加圖形效果(如模糊或顏色偏移)。它適用于元素背后的所有元素,為了看到效果,必須使元素或其背景至少部分透明。
注意兩者之間的差異,filter 是作用于元素本身,而 backdrop-filter 是作用于元素背后的區(qū)域所覆蓋的所有元素。
它們所支持的濾鏡種類:
可以看到,兩者所支持的濾鏡種類是一模一樣的。
也就是說,它們必然存在諸多差異,下面就讓我們逐一探討。
作用對象的差異
backdrop-filter 最常用的功能,就是用于實現(xiàn)毛玻璃效果。
我們通過實現(xiàn)毛玻璃效果來理解 filter 和 backdrop-filter 使用上的一些差異。
在 backdrop-filter 沒有誕生前,我們想實現(xiàn)這樣一個毛玻璃效果,是比較困難的:
有了它,實現(xiàn)毛玻璃效果就非常 Easy 了,看這樣一段代碼:
- <div class="bg">
- <div>Normal</div>
- <div class="g-filter">filter</div>
- <div class="g-backdrop-filter">backdrop-filter</div>
- </div>
- .bg {
- background: url(image.png);
- & > div {
- width: 300px;
- height: 200px;
- background: rgba(255, 255, 255, .7);
- }
- .g-filter {
- filter: blur(6px);
- }
- .g-backdrop-filter {
- backdrop-filter: blur(6px);
- }
- }
CodePen Demo -- filter 與 backdrop-filter 對比[2]
filter 和 backdrop-filter 使用上最明顯的差異在于:
- filter 作用于當(dāng)前元素,并且它的后代元素也會繼承這個屬性
- backdrop-filter 作用于元素背后的所有元素
仔細(xì)區(qū)分理解,一個是當(dāng)前元素和它的后代元素,一個是元素背后的所有元素。
理解了這個,就能夠明白為什么有了 filter,還會有 backdrop-filter。
效果上的差異
下面來看一些實際使用上,效果的差異。
譬如,我們想實現(xiàn)這樣一個圖片的蒙版 Hover 效果:
使用 backdrop-filter 可以輕松的勝任,因為它就是用于產(chǎn)生蒙版,作用于蒙版背后的元素,其核心偽代碼如下:
- <div></div>
- div {
- position: relative;
- background: url(https://www.wptunnel.com/wp-content/uploads/2021/07/wptunnel-hd-beautiful-wallpaper-4.jpg);
- }
- div::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- backdrop-filter: grayscale(100%);
- transition: .3s transform;
- }
- div:hover::before {
- transform: translate(100%, 0);
- }
思考如果使用 filter,如何實現(xiàn)上述的效果呢?比較麻煩,因為 filter 是作用于元素上的,所以,它只能是實現(xiàn)類似于這樣的 Hover 效果:
上述兩個效果 DEMO:CodePen -- filter VS backdrop-filter[3]
核心代碼:
- div {
- filter: grayscale(100%);
- transition: .3s filter;
- }
- div:hover {
- filter: grayscale(0);
- }
通過這個例子,應(yīng)該可以更好的理解它們之間的差異。
性能的差異
最早想寫這篇文章的初衷,是因為認(rèn)為 filter 和 backdrop-filter 可能實際存在性能上的差異。
但是隨著我使用多個 DEMO 驗證, 利用 filter 和 backdrop-filter 實現(xiàn)相同的動畫效果,獲取在動畫期間的頁面的幀率變化。
除了 Chrome 自帶的頁面幀率控制面板,還有一種利用 rAF 近似計算頁面幀率的方案,可以戳這里 -- Web 動畫幀率(FPS)計算[4]
實際對比之后,發(fā)現(xiàn)其實兩者并無多大性能上的差異。(當(dāng)然,也可能是我的實驗不夠嚴(yán)謹(jǐn)。歡迎有更為準(zhǔn)確的數(shù)據(jù)的同學(xué)指出)。
因此,如果利用 filter 和 backdrop-filter 都可以實現(xiàn)同一個效果,僅僅是性能這個角度,兩者在性能上其實不會有多大差異,二者選其一即可。
Backdrop Root
接下來這一點很有意思。有必要再好好講一講。
當(dāng)然,這一點 filter 和 backdrop-filter 都一樣,那就是作用了 filter 和 backdrop-filter 的元素(值不為 none),都會生成 Backdrop Root。
什么是 Backdrop Root 呢?(規(guī)范戳我 -- CSS 草案 -- Backdrop Root[5])也就是我們常說的,生成了自己的堆疊上下文(Stacking Context)。
我們直接來看,它會造成什么問題:
生成了 Backdrop Root 的元素會使 CSS 3D 失效
我之前寫過一個 3D 球的旋轉(zhuǎn)動畫,大概是這樣:
這個 Demo 你可以戳這里:CodePen Demo - 3D ball[6]:
然而,如果我們給上述動畫的容器,添加一個 filter 或者 backdrop-filter:
- {
- filter: blur(1px);
- }
整個 3D 動畫就會坍縮為 2D 動畫:
更為具體的探討,你可以看看我的這篇文章 -- 探究 CSS 混合模式\濾鏡導(dǎo)致 CSS 3D 失效問題[7]
作用了 filter 和 backdrop-filter 的元素會使內(nèi)部的 fixed 定位失效
另外這個問題也是比較常見的問題。
我們都知道,CSS 中 position: fixed 是相對于屏幕視口進(jìn)行定位的。
然而,作用了 filter 和 backdrop-filter 的元素的元素會使得其內(nèi)部的 position: fixed 元素不再相對于屏幕視口進(jìn)行定位,而是相對這個 Backdrop Root 元素進(jìn)行定位,其表現(xiàn)就是 position: fixed 定位的元素退化為了 position: absolute。
當(dāng)然,除了 filter 和 backdrop-filter 之外,在 CSS 中目前一共有 7 種方式可以讓元素內(nèi)部的 position: fixed 基于該元素定位:
- transform 屬性值不為 none 的元素
- 設(shè)置了 transform-style: preserve-3d 的元素
- perspective 值不為 none 的元素
- 在 will-change 中指定了任意 CSS 屬性
- 設(shè)置了 contain: paint
- filter 值不為 none 的元素
- backdrop-filter 值不為 none的元素
更為具體的探討,你可以看看我的這篇文章 -- fixed 定位失效 | 不受控制的 position:fixed[8]
兼容性的差異
最后,我們再來看看兼容性方面的差異。
到今天,不考慮 IE,filter 的兼容其實已經(jīng)非常非常的好了(2021-12-27):
而 dropback-filter 則一直沒得到 Firefox 系列的支持:
因此,F(xiàn)irefox 的跟進(jìn)支持一直是阻礙 dropback-filter 在生產(chǎn)環(huán)境使用最重要的一環(huán)。僅僅從兼容性角度考慮,使用它倆都能實現(xiàn)的效果我們應(yīng)該盡可能的選擇 filter。
最后
好了,本文到此結(jié)束,希望本文對你有所幫助 :)
參考資料
[1]backdrop-filter:
https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty
[2]CodePen Demo -- filter 與 backdrop-filter 對比:
https://codepen.io/Chokcoco/pen/WNjebrr
[3]CodePen -- filter VS backdrop-filter:
https://codepen.io/Chokcoco/pen/VwzQYRV
[4]Web 動畫幀率(FPS)計算:
https://github.com/chokcoco/cnblogsArticle/issues/17
[5]CSS 草案 -- Backdrop Root:
https://drafts.fxtf.org/filter-effects-2/#BackdropRoot
[6]CodePen Demo - 3D ball:
https://codepen.io/Chokcoco/pen/JwdvmJ
[7]探究 CSS 混合模式\濾鏡導(dǎo)致 CSS 3D 失效問題:
https://github.com/chokcoco/iCSS/issues/41
[8]fixed 定位失效 | 不受控制的 position:fixed:
https://github.com/chokcoco/iCSS/issues/24