CSS秘密花園:磨砂玻璃效果

jopen 9年前發布 | 22K 次閱讀 CSS 前端技術

CSS Secrets 》是 @Lea Verou 最新著作,這本書講解了有關于CSS中一些小秘密。是一本CSSer值得一讀的一本書,經過一段時間的閱讀,我、@南北和@彥子一起將在W3cplus發布一系列相關的讀后感,與大家一起分享。

問題

半透明顏色的一種應用是,使用它們作為背景。在照片或者顏色比較復雜的背景下,通過降低對比度,提高文本的可讀性。結果非常有效,但是閱讀起來仍然不是那么好,特別是非常低透明度的顏色或非常雜亂的背景的情況下。比如說,看看下圖效果:

其主要元素有一個半透明的白色背景,HTML如下:

<main>
    <blockquote>
        “The only way to get rid of a temptation[…]”
        <footer>—
            <cite>
                Oscar Wilde,
                The Picture of Dorian Gray
            </cite>
        </footer>
    </blockquote>
</main>

CSS代碼如下(不相關的內容就不再贅述):

body {
    background: url("tiger.jpg") 0 / cover fixed;
}
main {
    background: hsla(0,0%,100%,.3);
}

效果如上圖所示。

正如你看到的,文本內容確實很難閱讀,因為文本背后的圖像非常雜亂,而且背景顏色也只是 25% 的不透明值。當然,我們可以通過增加背景顏色的 alpha 參數的值來提高可讀性,但是效果可能就不是那么有趣了。

增加背景顏色的 alpha 值確實解決了可讀性的問題,但是也讓我們的設計變得一點都不好玩了。

在傳統的印刷設計中,這個問題通常是通過模糊照片上容納文本內容的那塊區域的背景來解決的。模糊后的背景就不會那么雜亂了,所以,上邊的文本可讀性也提高了。因為模糊的計算成本是昂貴的,過去在網頁和UI設計中使用這種技術,資源的損耗是讓人望而卻步的。但是,隨著GPU的改進和硬件加速變得越來越司空見慣,現在對于模糊效果的使用已經是非常普遍了。過去幾年里,在新版本的Microsoft Windows和Apple iOS 以及 Mac OS X中都可以看到這種技術。

帶模糊背景的半透明UI在過去幾年中變得非常普遍,因為模糊對資源的消耗已經變得不再昂貴(Apple iOS 8.1見圖左,Apple OS X Yosemite見圖右)。

在CSS中我們可以通過 blur() 濾鏡做出模糊元素的效果,這本質上是SVG模糊濾鏡原語的一個對應的硬件加速版本。但是,如果我們直接給我們的示例應用一個 blur() 濾鏡,整個元素都會被模糊,這樣可讀性就更差了。

為元素應用 blur() 濾鏡,結果更糟了

有沒有什么辦法,能讓它只應用在元素的backdrop上(也就是我們元素后面的背景的一部分)?

解決方案

如果是我們的元素有一個 background-attachment 屬性,值為 fixed ,可能就ok了,只是有點棘手。因為我們不能直接模糊我們的元素,我們可以將它應用到一個定位于元素背后的偽元素上,并讓偽元素的背景和 <body> 上的背景無縫匹配。

首先,我們添加一個偽元素,并設置絕對定位,所有的偏移量都為 0 ,這樣它就完美覆蓋整個 <main> 元素:

main {
    position: relative;
    /* [Rest of styling] */
}
main::before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    background: rgba(255,0,0,.5); /* for debugging */
}

背景也可以是non-fixed的,只是可能會導致混亂。

我們還應用了一個半透明的 red 背景,這樣我們可以看明白我們正在弄哪塊內容,否則在處理透明(也就是,invisible)元素的時候調試會比較困難。如圖所示:

偽元素模糊覆蓋在文本的上方

我們的偽元素就在我們的內容的上方,然后將其模糊。我們可以通過添加 z-index: -1; 來把它置于元素下方。

在用負的 z-index 值來將子元素移動到它的父元素下面時要小心:如果父元素是作為背景嵌套在其它元素中,子元素也會移到其它元素下方。

利用 z-index: -1; 將偽元素移動到父元素下方

現在是時候把半透明的紅色背景去掉了,用一個和我們背景相符的圖片,可以復制 <body> 的背景,或者直接拆分偽元素的規則。現在我們可以模糊了嗎?試一下:

body, main::before {
    background: url("tiger.jpg") 0 / cover fixed;
}
main {
    position: relative;
    background: hsla(0,0%,100%,.3);
}
main::before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    filter: blur(20px);
}

為什么不直接在 main::before 中使用 background: inherit ?因為這樣的話它會繼承 main 的背景,而不是 body 的背景,這樣偽元素得到的就只是一個半透明的白色背景。

圖注:偽元素的模糊是可行的,但是在邊緣處模糊較少,所以磨砂玻璃的效果也受了一點影響

如上圖所示,我們差不多完成了。中間的模糊效果看起來很完美,但是在接近邊緣的地方模糊比較少。這是因為模糊半徑(blur radius)會減少覆蓋有純色模糊的面積。為我們的偽元素應用一個紅色背景,有助于我們理解這是怎么回事。

圖注:添加一個紅色背景可以幫助我們理解

為了規避這個問題,我們讓偽元素至少比它的容器的尺寸大 20px (和模糊半徑的值相等),通過應用一個 -20px 或更小的 margin 值來讓它保持在一個安全的區域內,因為不同的瀏覽器可能會使用不同的模糊算法。如圖所示:

這修復了邊緣處褪色模糊的問題,但是現在在我們的容器外邊也有一些模糊,這使得它看起來像污跡而不像磨砂。幸好,這個問題也容易解決:我們只要應用為 main 應用 overflow: hidden; ,把多余的模糊剪掉即可。最后的代碼如下所示:

body, main::before {
    background: url("tiger.jpg") 0 / cover fixed;
}
main {
    position: relative;
    background: hsla(0,0%,100%,.3);
    overflow: hidden;
}
main::before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    filter: blur(20px);
    margin: -30px;
}

效果如下所示:

修復邊緣處淡去的模糊,但是我們的元素外邊仍然存在模糊

現在我們頁面的可讀性已經變得比剛開始的時候好多了,外觀也非常優雅。這種效果的降級是否優雅仍值得商榷。如果不支持濾鏡,我們看到的就是本節開頭的那個效果。我們可以通過調整背景顏色的透明度來讓降級效果的可讀性更好。

來自: http://www.w3cplus.com/css3/css-secrets/frosted-glass-effect.html

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