取自 Artifact Austin: Leaving Pixels Behind - Todd Parker,哪些圖片適合使用 SVG?
在網頁中,圖片通常在所有資源大小中佔了最多比例,最簡單的優化方式就是縮小圖片,但事實上在各式各樣的設備中,不同的網路速度、圖片處理效能、螢幕特性等等也是必須考量的因素,本篇文章整理了在品質和速度的權衡下進行圖片優化的各種手段。
使用 JPG、PNG 等等點陣圖之前,請先考慮以下幾點:
由於點陣圖通常檔案較大,且載入後會耗費較多瀏覽器效能和記憶體,有較大機率影響使用者體驗,此時就需要進行更多優化手段。
若一定得使用圖片,優先考量 SVG:
SVG 檔本身也可以透過工具如 SVGO 降低檔案大小。
優化圖片最直接的方式就是壓縮,壓縮的方式主要分為兩種:
圖片適合的壓縮方式要看網站的特性(是否接受失真、是否較關心檔案大小),以下幾點算是較為通用的部分:
除了 IE 之外,常見的瀏覽器都支援 WebP 圖片格式,網頁使用基本上是首選:
一款 Plugin based 圖片壓縮工具,可搭配 Webpack 使用,可依據想要壓縮的圖片格式和壓縮方式安裝插件、設定參數,來壓縮專案中用到的圖片。
使用 Webpack + url-loader
插件來打包圖片資源,當圖片大小在 limit
之內時會轉為 DataURL(Base64) 直接放入引入圖片的檔案裡面,因為請求資源時需要額外一次 Round trip,花費的時間會超過直接把圖片內容 Inline 到檔案內多出來的一點下載時間。
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
},
],
},
};
說到動圖首先想到的就是 GIF,不過 GIF 實在是非常大,不建議直接在網頁中使用,可用 FFmpeg 等工具把 GIF 轉成 MP4 或是 WebM(非常小,不需支援 IE 的首選)。
<video>
HTML 的 video
元素加上一些屬性後就能做到:自動開始、循環、無聲、避免全螢幕,和 GIF 沒兩樣,只差在不能直接使用 img
元素。
<video autoplay loop muted playsinline>
<source src="my-animation.webm" type="video/webm">
<source src="my-animation.mp4" type="video/mp4">
</video>
利用
source
和type
讓不支援 WebM 的瀏覽器使用 MP4。
在 img
加上一些屬性讓瀏覽器依據使用者螢幕大小自動判斷最適合的圖片,保持使用者體驗的同時不浪費流量和效能,例如:
<img
src="flower-large.jpg"
srcset="flower-small.jpg 480w, flower-large.jpg 1080w"
sizes="(max-width: 600px) 480px, 50vw"
/>
srcset
標示圖片名稱和圖片的實際大小。
sizes
可以設定 Media query,告訴瀏覽器此圖的 CSS 寬度(實際 CSS 還是要自己設),瀏覽器會依據 sizes
和 DPR、DPI 來決定要讀取 srcset
中的哪一張圖片。
注意可以使用各種單位、calc
,但不能用 %。
實際測試:https://web.dev/codelab-specifying-multiple-slot-widths/
DPR 代表螢幕中顯示一個 CSS pixel 所用的實際 Pixel 比例,例如 iPhone X 螢幕的 DPR 是 3,瀏覽器顯示一個 CSS pixel 實際上是用了 3 * 3 = 9 個 Pixels。
DPI 代表每個每寸內的 Pixels 數量,由於 iPhone X 的 DPI 較高,每個 Pixel 靠得很近,如果 CSS 設定 10px 就真的只顯示螢幕中的 10 個 Pixels 會讓元素小到幾乎看不到。
在此附上一個 Demo - Blur Canvas,當 Canvas 自身的寬度為 200,CSS 寬也設為 200px,在 DPR 為 2 的螢幕上顯示時每個色點會放大 2 * 2 = 4 倍,看起來就會糊糊的,若把 Canvas 的寬度設為 400,以同樣比例畫圖,再把 CSS 設為 200px,就能實際用上螢幕的所有 Pixels,顯示清晰的圖片。
src
當瀏覽器不支援 srcset
、sizes
時會 Fallback 到 src
,放在 src
的圖片應該要能涵蓋所有設備螢幕可用的大小。
即時轉換、優化圖片並進行快取,搭配 CDN 能夠讓圖片傳輸速度更快,可用網址輸入圖片轉換的參數,例如利用以下網址把圖片轉為 300 x 200 的大小:
https://<thumbor-server>/300x200/原始圖片網址.png
有些圖片不適合行動設備中使用,直接等比例縮小到手機寬度的話會讓圖片變得很醜,因此可以用到 Art direction 的技巧在不同螢幕寬度顯示不同的圖片。
在手機中顯示剪裁過的圖片
source
使用 picture
+ source
會回傳第一個 Media query 是 true 的圖片,否則 Fallback 到 img
,如果在 source
用了 Media query 就不需要 sizes
了。
<picture>
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
<source media="(min-width: 800px)" srcset="elva-800w.jpg">
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
實際測試:https://web.dev/codelab-art-direction/
瀏覽器的 HTML parser 還沒解析完 JavaScript、CSS 就能開始下載圖片,這也是為什麼需要 srcset
、sizes
等詳細大小資訊。
通常會以 3 到 5 為準,以使用者體驗和效能來說是越多越好,但需要更多 Server 儲存空間和撰寫更多 HTML。
sizes
?若能夠設定多種 sizes
區間能夠讓使用者體驗最好,更進一步還能根據網站使用者的螢幕寬度來決定,可參考 GA 搭配 https://screensiz.es/。
若真的只想使用一張圖片,且圖片是使用相對寬度,也必須確保該圖片夠大,剛好涵蓋大部分的使用者螢幕寬度。
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction
https://web.dev/fast/#optimize-your-images