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

2021-03-02 web前端開發
一、從哪裡說起呢…

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

於是,我們只要一套圖片就可以實現各種顏色效果了!

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

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

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

然而,都是有不足的,比方說:

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

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

一行:

transition: background-color .25s;

就可以讓交互變得細膩!

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偽元素可以直接插入圖片,注意,是直接圖片,不是元素的背景圖,語法如下:

.demo:after { content: url(xxx.png); }

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

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

.icon { width: 140px; height: 140px; background: #c8c8c8 url(icon.png) no-repeat 0 -140px;}↓.icon { /* 注意,只設高度不設寬度 */ height: 140px; background-color: #c8c8c8; overflow: hidden;}.icon:after { content: url(icon.png); position: relative; top: -140px;}

上面綠色注釋「只設高度不設寬度」點出了實現的關鍵:

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

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

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

四、結束語

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

更新於翌日
趁下班,研究了下為何有一定概率最後1~2個圖片會有色塊。我刷了幾十遍感受了下,尼瑪恍然大悟。原來,圖片是自上而下加載的,有背景色的時候,只是圖片尺寸得到了,但是,數據還沒完全下載下來,於是,此時,受制於網速原因,圖片上面加載好了,下面可能沒加載好。類似下面:

我之前有介紹過,可參見「漸進式jpeg(progressive jpeg)圖片及其相關」。

哈,知道了問題的原因,就知道該如何解決了。PS保存圖片時候,JPG是選擇連續,而PNG則是交錯:

我已替換原來圖片,現在,大家就真正不會出現一點點色塊了。

現在的小問題就是PNG壓縮同時保持交錯該怎麼處理,稍等,我再研究下~

更新於2016年2月28日
趁周末有研究了一下,一些壓縮工具,甚至包括Fireworks,都沒有看到png8 alpha格式同時支持交錯模式。高手在民間,希望有知道該如何處理的小夥伴不吝賜教!

PS: demo背景圖現在又換成png8 alpha壓縮圖了,省點流量~

相關焦點

  • CSS3 transform之scale縮放|transition之過渡動畫調整手記
    既然是滑鼠移上去後再發生變化,那首先需在css文件中,針對圖片的hover增加個樣式,縮放比例為1.1。就像以前用flash製作動畫一樣,缺少中間過渡(這個知識點,源於已經過世的flash)。(沒玩過動態的gif錄屏,用ps製作了一個動畫來模擬。)看來沒那麼簡單,還需要對圖片對應的樣式寫上css3的transition(過渡)。
  • vue中的transition
    動畫庫,如 Animate.css結合使用。其實就是綁定了class在transition標籤中,class引用了Animate.css的class樣式包。示例:<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"><div id="example-3">  <button @click="show = !
  • CSS樣式全部屬性和難記憶點(歸納)
    / positon postion(top/center/bottom/left/right)background-attachment背景是固定還是滾動scroll(滾動) fixed(固定)background-size設置圖片尺寸px 百分比/cover(保證填充滿背景區域,溢出部分隱藏)/contain(保證圖片始終完整顯示在背景區域) 例如:background-size: 50%;比原來小一半
  • CSS背景顏色、CSS背景圖片
    css可以添加背景顏色和背景圖片設置背景顏色這個背景顏色直接設置就好了,很簡單的。background: #eee;設置背景圖片此屬性值就是圖片的路徑。background-image:url(1.jpg);設置背景圖片是否平鋪background-repeat:值; repeat:平鋪(圖片鋪滿整個屏幕)(默認值)
  • 【vue2.0進階篇】用transition組件輕鬆實現過渡效果
    在離開過渡被觸發時生效,在下一個幀移除,也是一瞬間的事。 4.v-leave-active:離開過渡(leaving)的結束狀態。在離開過渡被觸發時生效,在 transition/animation 完成之後移除。
  • 面試題聯盟之CSS篇
    ,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載;import只在IE5以上才能識別,而link是HTML標籤,無兼容問題;link方式的樣式的權重 高於@import的權重.
  • 利用CSS、JavaScript及Ajax實現圖片預加載的三大方法
    圖片預先加載到瀏覽器中,訪問者便可順利地在你的網站上衝浪,並享受到極快的加載速度。這對圖片畫廊及圖片佔據很大比例的網站來說十分有利,它保證了圖片快速、無縫地發布,也可幫助用戶在瀏覽你網站內容時獲得更好的用戶體驗。本文將分享三個不同的預加載技術,來增強網站的性能與可用性。
  • 藍韻鐵軍 | animation、transition、transform、translate 傻傻分不清
    css屬性很多,並且有些無論是字母的拼寫還是字面上的意思,都容易混淆,比如下圖的幾個屬性,是不是也混淆過你呢?
  • HTML CSS整理筆記
    36.CSS3設置背景樣式: (1)background-color:背景色不能繼承,其默認值是透明transparent (2)background-image:url(圖片路徑)、none(不顯示背景圖像) (3)background-repeat:背景圖像重複平鋪 repeat(沿水平和垂直方向)、no-repeat(不平鋪
  • 42個來自《 CSS世界》中的實用技巧
    7、優雅的圖片未加載或加載失敗效果需要注意的是,圖片顯示完成後,img會成為「替換元素」,而替換元素是無法設置偽元素的,因為內容被圖片替換掉了;還需要注意attr裡面的變量不能加雙引號。*/ transition: transform .2s; } img:hover::after { /* alt 信息顯示 */ transform: translateY(0); } </style>8、CSS的懸浮圖片替換效果需要注意的是,如果快捷保存圖片
  • 「金三銀四」,讓我們愉快的開始準備Web面經吧:CSS篇
    >: clear: both創建父級 BFC父級設置高度7.link 與 @import 的區別link功能較多,可以定義 RSS,定義 Rel 等作用,而@import只能用於加載css當解析到link時,頁面會同步加載所引的 css,而@import所引用的 css 會等到頁面加載完才被加載@import需要 IE5 以上才能使用link可以使用 js 動態引入,@import不行
  • 面試整理(三)CSS部分
    css sprite 是什麼,有什麼優缺點概念:將多個⼩圖⽚拼接到⼀個圖⽚中。通過 background-position 和 元素尺⼨ 調節需要顯示的背景圖案。如何避免a- Flash Of Unstyled Content :⽤戶定義樣式表加載之前瀏覽器使⽤默認樣式顯示⽂檔,⽤戶樣式加載渲染之後再從新顯示⽂檔,造成⻚⾯閃爍。b- 解決⽅法:把樣式表放到⽂檔的 <head> 5.
  • 有趣的CSS小示例:好看的皮囊千篇一律,有趣的靈魂萬裡挑一
    文字加載...動畫html正在加載中<dot>...原來是dot元素,沿著Y軸在循環位移,隱藏掉就讓你看到了加載的動畫效果。border 實現邊框當你需要這樣一個上傳文件,按鈕時,你考慮的是找設計弄個圖片,還是自己寫一個???其實CSS寫,也很簡單的。
  • 10 個 GitHub 上超火的 CSS 技巧項目,找到寫 CSS 的靈感!
    這裡可以讓你尋找到使用或者是學習 CSS 的靈感,以分類的形式,展示不同 CSS 屬性或者不同的課題使用 CSS 來解決的各種方法。包含了:布局(Layout)、陰影(box-shadow、drop-shadow)、偽類/偽元素、濾鏡(fliter)、邊框(border)、背景/漸變(linear-gradient/radial-gradient/conic-gradient)、混合模式(mix-blend-mode/background-blend-mode)、3D、動畫
  • 使用簡單 好看的CSS加載動畫源碼
    今天小編分享的css-spinners,它自帶的CSS加載樣式很漂亮,圖案色彩豐富,花樣多多,就算不用它的CSS,也可以按它的動畫來做成GIF圖像。loading樣式有花形、心形、指針、圓形旋轉、進度條以及常見的菊花加載圖案:使用教程CSS Spinners除了輕量級外,使用也十分的簡單,下面來看看教學:STEP 1: 引入CSS文件加載動畫樣式有單個以及全部,如果用戶只需要一個加載動畫,就選擇對應的CSS文件。
  • 巧用css圓角實現有點意思的加載動畫
    css的圓角屬性來實現有點意思的加載動畫.如果想學習更多css實用技巧, 可以參考筆者以下的文章:css的border屬性和border-radius屬性筆者在前面的文章中也分享過了如何利用border來實現不同的形狀, 比如三角形, 如下為原理圖:利用這個原理我們只要把元素的border-radius 設置為圓形(比如50%), 我們是不是就能實現一個餅圖了呢?
  • 【第795期】Vue2.0 Transition常見用法全解惑
    什麼是過渡Vue只有在插入,更新或者移除DOM元素時才會應用過渡效果,過渡效果的應用可以通過不同方式實現,官方文檔中提到了如下幾種:在CSS過渡和動畫中自動應用class;配合使用第三方的CSS動畫庫,如Animate.css;在過渡鉤子函數中使用JavaScript直接操作DOM;
  • Vue3+TS系統學習九 - Vue3實現過渡動畫
    過渡的模式mode我們來看當前的動畫在兩個元素之間切換的時候存在的問題:<template> <div> <div> <button @click="show = !
  • CSS常見題型,你會幾道?(面試必問)
    CSS 文件,還可以定義 RSS、rel 連接屬性等加載順序區別加載頁面時,link標籤引入的 CSS 被同時加載;@import引入的 CSS 將在頁面加載完畢後被加載。等同於:first-child:last-child或 :nth-child(1):nth-last-child(1)E:only-of-type匹配父元素下使用同種標籤的唯一一個子元素,等同於:first-of-type:last-of-type或 :nth-of-type(1):nth-last-of-type(1)E:empty匹配一個不包含任何子元素的元素,注意,文本節點也被看作子元素屬性描述transition
  • 過渡動畫和關鍵幀動畫
    一、CSS3 過渡transitioncss3的transition允許css的屬性值在一定的時間區間內平滑地過渡。這種效果可以在滑鼠單擊、獲得焦點、被點擊或對元素任何改變中觸發,並圓滑地以動畫效果改變CSS的屬性值transition-property:檢索或設置對象中的參與過渡的屬性transition-duration:檢索或設置對象過渡的持續時間transition-delay:檢索或設置對象延遲過渡的時間