CSS鏤空圖片transition過渡初載入背景色塊問題解決

發表於2016-02-25

一、從哪裡說起呢…

數年前寫過一篇很實用的文章,介紹了一個很有創意的技術:“CSS背景色鏤空技術實際應用及進階”,講的圖示圖形為了更容易控制其顏色,對圖片採用了鏤空的處理。例如,下面這張圖片(點選會有隨機的背景色):
sprite背景圖

於是,我們只要一套圖片就可以實現各種顏色效果了!
Chrome下color控制元件實現的效果 張鑫旭-鑫空間-鑫生活

而不要類似下面這樣,為了各種狀態湊齊完整的葫蘆七兄弟:
各種顏色圖示

除了節約圖片資源大小,CSS鏤空圖片技術還有一個好處,就是由於我們的圖示顏色是CSS屬性控制的,因此,我們可以漸進使用transition實現過渡效果,讓互動更細膩。

說到CSS控制圖示顏色,我們自然而然會想到icon fonts, 或者使用SVG sprites技術,或者使用混合模式來實現。

然而,都是有不足的,比方說:
新浪微博的icon fonts

SVG的相容性以及混合模式的理解成本和環境限制等。

因此,轉了一圈,會發現,有時候,還是圖片來得最實在,且看下面demo實現的效果,雖然使用的是background-image實現的,但是hover態,selected態都和文字hover transition過渡,這是傳統背景圖片所沒法實現的。

您可以狠狠地點選這裡:鏤空背景圖片下的transition過渡效果

一行:

就可以讓互動變得細膩!

demo點選效果截圖

default, hover, selected三種顏色態僅僅一個系列圖片就搞定(見下圖),看上去很贊,贊到飛起來。

背景圖片示意

然而,這種實現有一個致命的不足,就是CSS的載入和背景圖片的載入不是同步的,尤其首次載入的時候,圖片是非同步的,具有明顯的延遲,於是,我們會看到非常醜陋的色塊在一瞬間出現了(大家可以強刷demo體驗到)!

討厭的色塊

正所謂“開發可忍設計不可忍”,這種問題顯然是非常嚴重的,直接導致此看上去很酷的方法瀕臨夭折的邊緣,看上去只適用於預設隱藏的元素。

大家莫慌莫慌,有我在呢!

二、base64 url圖片與非同步色塊問題解決

這個很好理解,就是把背景圖片轉換成base64 url圖片,因為是整合在CSS檔案中的,因此,基本上是同時呈現,不會出現色塊。然而,此方法侷限性很明顯,就是隻適用於一些尺寸很小的小圖。類似上面demo的背景圖片,有5K多大小,直接內嵌在CSS檔案中,就像是身體里長了個瘤子,太笨重了,而且base64渲染是比較燒效能的,圖片越大越慢,且IE7瀏覽器很難支援base64圖片。

因此,此方法在這裡不適用,難道要天亡我也?非也!

三、content url圖片與非同步色塊問題解決

6年前,也就是10年的時候,我在“CSS content內容生成技術以及應用”一文中首次介紹了CSS content url圖片內容生成技術,就是before, after偽元素可以直接插入圖片,注意,是直接圖片,不是元素的背景圖,語法如下:

OK, 大家如果觀察過頁面圖片的載入,應該注意到這麼個現象,就是如果圖片沒有通過HTML屬性或者CSS值限定width/height寬高的時候,在瀏覽器get到圖片的原始尺寸之前,圖片佔據的空間大小是0. 我們如果重新整理浪微博,會發現頁面高度蹭蹭蹭地往上漲,就是這麼個原因,這種不對圖片限定尺寸的做法在網頁佈局中是不推薦的,因為,會造成頁面佈局重繪,影響載入效能。

但是,存在必有道理,在這裡,我們就可以好好地利用圖片為載入時候佔據空間為0的特性避免出現色塊的問題,怎麼解決呢?就是把元素的background-image url值變成偽元素的content url值;同時background-position定位改成其他定位,如relative定位,如下程式碼示意:

上面綠色註釋“只設高度不設寬度”點出了實現的關鍵:

頁面渲染流程如下,1. CSS載入;2. 對應DOM渲染,背景色出現;3.拉取DOM樣式對應背景圖片。

傳統實現就是從2到3的時候出現了問題,圖片從伺服器重新請求,導致了時間差,出現了色塊。而我們這裡的實現就不一樣,當我們背景色出現,但是圖片未載入的時候,由於我們的CSS沒有設定元素的寬度,加上圖片未載入佔據寬度為0的特性,於是,在2完成3即將進行的時候,我們整個元素的高度140px, 寬度0,寬度是0啊!這意味著什麼,意味著元素看不見啊,也即是雖然有背景色,無奈尺寸為0,我們是看不出有一絲絲背景色的;然後等圖片請求到,自然就填滿了元素,背景色也被遮掉了。沒有了時間差,於是,完美解決了色塊出現的問題!

完美

您可以狠狠地點選這裡:content url生成的解決色塊問題demo

IE7瀏覽器
什麼年代了,還IE7瀏覽器,要是喜歡,可以使用expression表示式,或者直接JS打個補丁,小弟我現在對這些瀏覽器不奉陪了!

四、結束語

我測試發現,時間差似乎就Chrome瀏覽器比較明顯,另外後面的content url有一定機率會出現最後一個有色塊的情況,按照道理應該不會的,現在太晚了,都2點了,我有時間在研究研究。

相關文章