本文是系列第三篇。系列文章: 現代圖片性能優化及體驗優化指南 - 圖片類型及 Picture 標簽的使用 現代圖片性能優化及體驗優化指南 - 響應式圖片方案 圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬的消耗是十分巨大的。 對圖片的性能優化及體驗優化在今天就顯得尤為重要。本文, ...
本文是系列第三篇。系列文章:
圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬的消耗是十分巨大的。
對圖片的性能優化及體驗優化在今天就顯得尤為重要。本文,就將從各個方面闡述,在各種新特性滿頭飛的今天,我們可以如何儘可能的對我們的圖片資源,進行性能優化及體驗優化。
圖片的寬高比、裁剪與縮放
OK,下麵進入到我們的第三個模塊,圖片的寬高比、裁剪與縮放。我們會介紹 4 個新的特性:
aspect-ratio
object-fit
object-position
image-rendering
使用 aspect-ratio
避免佈局偏移
很多時候,只能使用固定尺寸大小的圖片,我們的佈局可能是這樣:
對應的佈局:
<ul class="g-container">
<li>
<img src="http://placehold.it/150x100">
<p>圖片描述</p>
</li>
</ul>
ul li img {
width: 150px;
}
當然,萬一假設後端介面出現一張非正常大小的圖片,上述不加保護的佈局就會出問題:
所以對於圖片,我們總是建議同時寫上高和寬,避免因為圖片尺寸錯誤帶來的佈局問題:
ul li img {
width: 150px;
height: 100px;
}
同時,給 <img>
標簽同時寫上高寬,可以在圖片未載入之前提前占住位置,避免圖片從未載入狀態到渲染完成狀態高寬變化引起的重排問題。
當然,到今天,我們還可以使用 aspect-ratio
設定圖片的高寬比。
aspect-ratio
CSS 屬性為容器規定了一個期待的寬高比,這個寬高比可以用來計算自動尺寸以及為其他佈局函數服務。
像是上面的代碼,我們就可以替換成:
ul li img {
width: 150px;
aspect-ratio: 3 / 2;
}
當然,有的時候,我們的佈局是響應式動態在變化的,容器的寬度也是不確定的,因此,有了 aspect-ratio
之後,我們的寫法就可以更佳的舒服。
ul li img {
width: 100%;
aspect-ratio: 3 / 2;
}
這裡,容器基於 Flex 彈性佈局或者響應式佈局,其寬度是不固定的,但是圖片的寬高比是固定的,使用 aspect-ratio: 3 / 2
就能非常好的適配這種情況。
我們藉助了 aspect-ratio 這個 CSS 中較新的屬性來始終自動獲得正確的寬高比,無論其父元素的寬度如何變化。
當然,
aspect-ratio
不僅僅只是能運用在這裡,在aspect-ratio
出現之前,我們只能通過一些其它的 Hack 方式,譬如設置padding-top
等方式模擬固定的寬高比。在aspect-ratio
之後,我們終於有了設定容器固定寬高比的能力。
object-fit
避免圖片拉伸
當然,限制高寬也會出現問題,譬如圖片被拉伸了,非常的難看:
這個時候,我們可以藉助 object-fit
,它能夠指定可替換元素的內容(也就是圖片)該如何適應它的父容器的高寬。
ul li img {
width: 150px;
aspect-ratio: 3 / 2;
object-fit: cover;
}
利用 object-fit: cover
,使圖片內容在保持其寬高比的同時填充元素的整個內容框。
object-fit
的取值有 fill
、none
、contain
、cover
,與 background-size
類似,可以類比記憶。
也可以看看這張圖,很易於理解:
object-fit
還有一個配套屬性 object-position
,它可以控製圖片在其內容框中的位置。(類似於 background-position
),預設是 object-position: 50% 50%
,如果你不希望圖片居中展示,可以使用它去改變圖片實際展示的 position。
ul li img {
width: 150px;
aspect-ratio: 3 / 2;
object-fit: cover;
object-position: 50% 100%;
}
像是這樣,object-position: 100% 50%
指明從底部開始展示圖片。這裡有一個很好的 Demo 可以幫助你理解 object-position
。
CodePen Demo -- Object position
使用 image-rendering
設置圖片縮放演算法
相對於上面幾個新特性,image-rendering
會更為冷門。
很多時候,我們設置一個圖片在頁面上的展示大小為 200px x 200px
,但是圖片的原始尺寸可能是 800px x 800px
,也可能是 50px x 50px
。
這個時候,我們就可以利用 image-rendering
,設置圖片在縮放狀態下的展示演算法。
image-rendering
在特定的場景下,能夠起到奇效。
來看這樣一個有意思的 DEMO,假設我們有這樣一個原圖效果,它是一個二維碼,大小為 100px x 100px
:
如果我們將它放大,放到很大,明顯,這個二維碼會失真,像是這樣:
OK,在這種放大失真的情況想,可以使用 image-rendering
改變圖片縮放演算法,這裡我們試一下 image-rendering: pixelated
:
.img {
image-rendering: pixelated;
}
效果變化,如下圖所示:
可以看到,image-rendering: pixelated
處理過的圖像,竟然變得如此清晰!
CodePen Demo -- QrCode Image-rendering demo
來看看 image-rendering
的幾個取值:
image-rendering: auto
:自 Gecko 1.9(Firefox 3.0)起,Gecko 使用雙線性(bilinear)演算法進行重新採樣(高質量)。image-rendering: smooth
:使用能最大化圖像客觀觀感的演算法來縮放圖像image-rendering: high-quality
:與 smooth 相同,但更傾向於高質量的縮放。image-rendering: crisp-edges
:必須使用可有效保留對比度和圖像中的邊緣的演算法來對圖像進行縮放,並且,該演算法既不會平滑顏色,又不會在處理過程中為圖像引入模糊。合適的演算法包括最近鄰居(nearest-neighbor)演算法和其他非平滑縮放演算法,比如 2×SaI 和 hqx-* 系列演算法。此屬性值適用於像素藝術作品,例如一些網頁游戲中的圖像。image-rendering: pixelated
:放大圖像時,使用最近鄰居演算法,因此,圖像看著像是由大塊像素組成的。縮小圖像時,演算法與 auto 相同。
雖然規範定義了挺多值,但是實際上,現代瀏覽器基本暫時只支持:auto
、pixelated
、以及 -webkit-optimize-contrast
(Chrome 下的 smooth)。
看描述都會挺懵逼的,實際使用的時候,最好每個都試一下驗證一下效果。總結而言,image-rendering
的作用是在圖像縮放時,提供不一樣的渲染方式,讓圖片的展示形態更為多樣化,或者說是儘可能的去減少圖片的失真帶來的信息損耗。
我們再看一個 DEMO,原圖如下(例子來源於 W3C 規範文檔):
實際效果:
當然,看上去 pixelated
的效果挺好,這是由於這是一張偏向於矢量的圖片,細節不多,對於高精度的人物圖,就不太適用於 pixelated
,容易把圖片馬賽克化。
真正規範希望的在放大後讓圖片儘可能不失真的 crisp-edges
效果,目前暫時沒有得到瀏覽器的實現。後面可以期待一下。
CodePen Demo -- Image-rendering demo
總結一下
這一章,我們介紹了 4 個較新的 CSS 特性:
aspect-ratio
:控制容器的寬高比,避免產生佈局偏移及抖動object-fit
:設定內容應該如何適應到其使用高度和寬度確定的框,避免圖片拉伸object-position
:基於object-fit
,設置圖片實際展示的 position 範圍image-rendering
:控製圖片在縮放狀態下的展示演算法
合理利用它們,可以給用戶在圖片上以更好的體驗。
當然,本文是現代圖片性能優化及體驗優化指南的第三篇,後續將給大家帶來圖片在:
- 懶載入/非同步圖像解碼方案
- 可訪問性以及圖片資源的容錯及錯誤處理
上的現代解決方案,感興趣的可以提前關註。
最後
OK,本文到此結束,希望本文對你有所幫助