2014年12月7日

[教學]減少網頁 reflow(回流) 的 CSS 實作技巧﹍優化網站效能(3)

A+
在增進網頁效能的執行事項之中,減少瀏覽器回流(reflow)是重要的一環。然而 reflow 這個名詞不常見、且翻譯也不易理解,不如稱之為「瀏覽器重新佈局」、或「網頁區塊重新安排」會來得白話一些。而為何要減少 reflow?因為它會造成 CPU 無謂的重複運算,消耗瀏覽器效能及渲染頁面的時間

關於這件事先說結論,除非網站 Javascript(簡稱 js) 大部分是自己寫的,否則站長能做的改善有限,因為 js 寫得好不好無法由自己控制。因此如何減少 reflow,本篇著重在可以經由修改範本來改善的部分,也就是我們能 "自力救濟" 的部分

在 Blogger 平台如果硬要打分數的話,以這個系列文來說,能完成「優化網站效能該注意哪些事? (1)最關鍵的考量因素」起碼可拿到 50 分以上,完成「 HTML / Javascript / CSS 最佳化處理」約可拿到 20 分;而本文按照教學設定正確的 css 最多可拿到 5~10 分,如能自行解決 js 可額外拿到 5~15 分,依範本中需要處理的多寡而定。



一、瀏覽器運作原理


1. 瀏覽器如何渲染網頁

要改善 reflow 現象,得從瞭解瀏覽器運作原理下手。這篇「瀏覽器渲染原理」非常值得推薦,簡短又生動地說明了網頁大致的渲染(render)流程。以下用精要的文字歸納 reflow 的定義:

  • 當網頁任一個區塊,其尺寸或位置產生變化時,瀏覽器必須重新計算受影響的區塊(尺寸或位置),重新安排區塊位置、重新繪製畫面的整個流程,稱為 reflow(英文字面來看,就是重新流動一次)。

當一個改變造成影響的區塊越多,可想而知瀏覽器的運算會有多累了。如前所述,非程式設計者的我們,無法自行優化 js,不過根據參考文章,我們可以自行優化 CSS 的部分:替所有圖片設定寬、高的參數。




以上為區塊變動時,reflow 行為的示意圖




當 CSS 參數改變、但區塊尺寸沒變動的話,只會進行重繪(repaint),而不會引起 reflow。

由於原文的圖片掛了,以上兩圖取自轉貼原文的網址:http://justjavac.iteye.com/blog/644235



2. 替圖片設定尺寸

當圖片沒有設定尺寸參數時,瀏覽器在下載圖片之前,便無法知道這張圖片到底多大,所以不會為圖片保留座位。你一定有這樣的經驗:

  • 逛網頁時,會看到文章中的文字先顯示出來,忽然間一張圖片顯示了出來,把原來的文字從圖片顯示的位置,擠到了下方去。而一篇文章中放了幾張圖片,就可能依序重複發生以上的現象。

以上就是頁面多次發生 reflow 的現象,圖片之後的內容、區塊越多,瀏覽器因為 reflow 所耗費的運算就越龐大。解決的方法現在我們已經知道,事先幫圖片用 CSS 設定好寬、高,那麼瀏覽器會先幫圖片把這個區塊的尺寸保留起來(圖片未顯示前的空白區塊),自然就不會發生 reflow 的無謂運算了。


3. 舉一反三

瞭解原理之後,從圖片的處理我們可聯想到,其他區塊也可用同樣的方式來處理,最大程度地避免 reflow 發生。

  • Iframe:許多 Facebook 外掛提供了 Iframe 的形式,例如「讚按鈕」,如果把網頁所有 Iframe 都預先設定好寬、高,這些 Iframe 就不會產生 reflow。
  • 外掛工具區塊:很多外掛工具都是用動態產生,或是一開始設定 display: none,產生內容後再取消隱藏,都會導致 reflow 的現象。如能確定尺寸的話,一開始就先把區塊 DIV 設定寬、高,或是隱藏的方式改為 visibility: hidden,都能有效減少 reflow。


4. 瀏覽器運作的原理

這部分算是補充的內容,如果想要做到完美,那麼必須精確瞭解所有瀏覽器運作的原理,才能進行針對性的效能改善。有興趣的讀者可參考這篇值得推薦的濃縮文章「瀏覽器的渲染原理簡介」,其原文來自於「瀏覽器的工作原理:新式網絡瀏覽器幕後揭秘」。

程式設計師可經由以上這兩篇文章,瞭解 js 應該如何操作,來減少 reflow 的產生。



二、圖片添加尺寸參數


接下來進入實作階段,幫圖片加上尺寸的參數算是很簡單,但又不是那麼簡單的任務。首先,要如何得知一張圖片的實際寬、高的像素值呢?

1. 取得圖片的尺寸

最簡單的方法,將圖片另存新檔 → 用看圖軟體查看尺寸。

只不過圖片數量一多,這個方法的操作步驟繁冗,不是最有效率的方式。


2. 利用開發人員工具

如果熟悉瀏覽器的操作,例如「Chrome 開發人員工具」,使用放大鏡功能,游標移到圖片區塊,就能立即得到圖片尺寸。

以 WFU BLOG 網站 logo 為例,使用此工具的放大鏡後,滑鼠移到圖片即顯示尺寸為 100 x 100 px,如下圖紅框:




3. CSS 設定

A. 單張圖片:使用行內 CSS 即可,例如網站 logo 的圖片 html 新增紅色參數如下──

<img style="width: 100px; height: 100px;" src="http://1.bp.blogspot.com/-vhIWukZmniI/VA3My_ptRfI/AAAAAAAAKM0/DaF4uGRxB0Q/s100/wfublog-logo-8abeb7.png"/>

B. 多張圖片:如果有多張尺寸一樣的圖片,使用行內 CSS 比較沒效率,可在圖片 html 設定 class,這個 class 的 CSS 參數即可套用到多張圖片──

<img class="wfu_logo" src="圖片1.jpg"/>

<img class="wfu_logo" src="圖片2.jpg"/>

<style>
.wfu_logo {
width: 100px;
height: 100px;
}
</style>

以上 style 區間的程式碼,請參考「如何讓 CSS 執行有效率」,放到範本中 </head> 之前的位置。



三、實作技巧


看完「二、圖片添加尺寸參數」的說明後,當準備開始在自己的網站實作時,讀者應該就會發現問題來了,而且是令人頭大的問題:

  • 舊文章的圖片數量是天文數字,處理不完。
  • 新文章的圖片一開始可能無法知道尺寸,要得知尺寸、設定尺寸的過程,是一件很麻煩的事!

1. 處理文章中的圖片

舊文章的處理後續再提,如果是新文章中的圖片,Blogger 平台有個簡單快速的方法可以設定。

使用 Blogger 的文章編輯器 → 切換到 HTML 模式 → 上傳圖片 → 對齊方式選「無」, 完畢後大致會出現以下格式的圖片 html 碼:

<a href="http://2.bp.blogspot.com/-sljaRxqJ7qY/VILpym1UCCI/AAAAAAAAKss/rLOksSgIXI4/s1600/chrome-develop-tool-img-size.png" imageanchor="1"><img border="0" src="http://2.bp.blogspot.com/-sljaRxqJ7qY/VILpym1UCCI/AAAAAAAAKss/rLOksSgIXI4/s400/chrome-develop-tool-img-size.png"/></a>

接著切換到撰寫模式 → 對著上傳的圖片按下去,會出現下圖選項──



請選擇圖片想要顯示的尺寸,盡量不要選對齊方式(html會非常亂、也會有很多麻煩),然後再切回 HTML 模式,奇妙的事發生了,以下是新的圖片 html 碼:

<a href="http://2.bp.blogspot.com/-sljaRxqJ7qY/VILpym1UCCI/AAAAAAAAKss/rLOksSgIXI4/s1600/chrome-develop-tool-img-size.png" imageanchor="1"><img border="0" src="http://2.bp.blogspot.com/-sljaRxqJ7qY/VILpym1UCCI/AAAAAAAAKss/rLOksSgIXI4/s400/chrome-develop-tool-img-size.png" height="238" width="400" /></a>
請見紅字的參數,Blogger 自動幫我們依寬高比例計算、並加上了圖片尺寸,這樣的設計可以說是幫我們節省了不少麻煩。如果有任何圖片想自動設定尺寸,倒是可以藉助 Blogger 文章編輯器的這項功能!


2. 其他區塊的圖片

網站之中、文章區塊以外的圖片,尺寸通常都是固定的,例如網站 logo、社交按鈕、各種小圖示等等,這些都可經由「二、圖片添加尺寸參數」的流程及技巧,來找出圖片尺寸,並加上 CSS 參數。


3. 小工具的圖片

以「相關文章 V2」為例,可以設定固定長、寬的縮圖,所以不會引起 reflow。

而側邊欄的小工具很多都會使用圖片,例如熱門文章、最新文章、最新留言(的頭像)等等,最好也使用固定的縮圖尺寸,方便設定參數。如果懂 js 的話可自行修改程式碼,將來這幾個小工具出更新版時,也會使用固定縮圖尺寸的參數,來減少 reflow 的機會。



四、其他問題


最後剩下舊文章的圖片尺寸,由於數量龐大並不好處理,最好是能藉由 js 自動批次處理來節省操作時間。下一篇的構想將是利用 Lazy Load 來延遲圖片載入的同時,一併加上圖片尺寸的參數,算是一舉兩得,請讀者靜候。


優化網站效能 系列文章:

2 則留言:

  1. 感謝WFU大大提供好文~
    但如果已經寫好blogger內圖片的CSS樣式:
    例如 .post img {max-width: 95%; height: auto;} 等
    這樣新文章中的處理方法 雖然能解決瀏覽器 reflow 的問題
    不過因為套用整體樣式 多少會變形而犧牲掉圖片的畫質了
    期待下一篇出現解決方法 :)

    回覆刪除
    回覆
    1. 不客氣~下一篇不會太久。

      使用 max-width 的作用為,不讓圖片寬度超出文章區塊的邊界,這是使用大圖時,防止版面破裂的必要語法;如果圖片有使用超連結、或安裝 fancybox 這類燈箱,按下後還是能看到大尺寸的圖片。

      另外,max-width 無法避免 reflow,因為瀏覽器還是無法知道這張圖的寬度為何,不曉得要替圖片保留多大的位置喔~

      刪除

張貼留言注意事項:

◎ 勾選「通知我」可收到後續回覆的mail!
提問請附網址、詳細描述狀況,如提供的資訊不足,則無法回覆。
◎ 請在相關文章留言,與文章無關的主題請至「Blogger 中文論壇」。
◎ 若詢問 CSS 、非官方範本問題、或貴站為商業網站 ,請參考「本站諮詢頁面」→「1. 諮詢服務」
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 若發現留言不見了,通常是因為 "複製貼上" 的內容常被系統判定為垃圾留言,請不用擔心,我會定期將留言恢復。
◎ 本站「已關閉自刪留言功能」。