探索Web上圖片使用方式

來自專欄 W3cplus的故事69 人贊了文章

圖片在Web上的使用佔比已經非常的高,特別是在手淘互動這樣的環境之下,我們每一個項目的圖片使用量都非常的大。如果能把圖片用好,的確是件不容易的事情,而且面對的挑戰也不小。經常會碰到有關於圖片如何載入,如何適配,如何優化等等。

另外在移動端開發中,很多同學在Web上使用圖片的方法一般都是通過<img>標籤和CSS的background-image屬性來處理。也正因如此,很多同學卻忘記了這兩者應該如何?怎麼使用又是最優的。甚至有很多前端同學都已經忘記了這兩者的差異是什麼?

加上Web的技術不斷革新,事實上除了前面提到的載入圖片的方式之外,還有其他的方式,比如HTML5的<picture>(雖然這個元素標籤曾經一度廢棄過,但後來又添加回來了)。就算還是使用img標籤,也有了新的優化,比如imgsrcset屬性。

那麼面對這麼多的變化,以及使用的場景,我們應該怎麼來選擇,纔是最優的選擇。今天這篇文章,我們就來一起探討一下這些東西,希望大家會喜歡。

Web引入圖片的姿勢

Web上如何引入圖片,其實前面已經簡單的提到過。這也是探索Web上圖片最基礎的部分。所以花點時間來簡單的描述一下。一般在Web上引入圖片,大體分為兩種類型,其一是通過 HTML元素引入圖片,其二是通過 CSS樣式引入圖片

HTML元素引入圖片

通過HTML元素在Web上引入圖片最常見的方式是通過<img>元素來引入。比如:

<img src="logo.png" alt="w3cplus" />

img元素是通過src來引入圖片資源(圖片的路徑),除此src屬性之外,還有其屬性,比如上例中的alt屬性提供有意義的描述(當圖片載入失敗的時候,alt的內容將會顯示在Web上。這些描述有助於提高您的網站的可訪問性,因為它們能提供語境給屏幕閱讀器及其他輔助性技術),widthheight等常用屬性。在HTML5中還給img元素添加了兩個新屬性 srcsetsizes

srcset 屬性增強了 img 元素的行為,讓您能夠輕鬆地針對不同設備特性提供多種圖片文件。類似於 CSS 原生的 image-set 函數,srcset 也允許瀏覽器根據設備特性選擇最佳圖像,例如,在 2x 顯示屏上使用 2x 圖像,將來甚至允許在網路帶寬有限時對 2x 設備使用 1x 圖像。

在不支持 srcset 的瀏覽器上,瀏覽器只需使用 src 屬性指定的默認圖像文件。 正因如此,無論設備能力如何,一定要始終包含一個在任何設備上都能顯示的 1x 圖像。如果 srcset 受支持,則會在進行任何請求之前對逗號分隔的圖像/條件列表進行解析,並且只會下載和顯示最合適的圖像。 比如,你現在可以換個姿勢使用<img>來根據不同的環境載入不同的圖片:

<img srcset="quilt_2/detail/large.jpg 1920w, quilt_2/detail/medium.jpg 960w, quilt_2/detail/small.jpg 480w" src="quilt_2/detail/medium.jpg" alt="Detail of the above quilt, highlighting the embroidery and exotic stitchwork.">

另外,imgsizes屬性也非常的強大。該屬性可以使圖片資源尺寸的值被用來指定圖像的預期尺寸。當srcset使用w描述符時,用戶代理使用當前圖像大小來選擇srcset中合適的一個圖像URL。被選中的尺寸影響圖像的顯示大小。如果沒有設置srcset屬性,或者沒值,那麼sizes屬性也將不起作用。來看一個簡單的例子:

<img src="lighthouse-200.jpg" sizes="50vw" srcset="lighthouse-100.jpg 100w, lighthouse-200.jpg 200w, lighthouse-400.jpg 400w, lighthouse-800.jpg 800w, lighthouse-1000.jpg 1000w, lighthouse-1400.jpg 1400w, lighthouse-1800.jpg 1800w" alt="a lighthouse">

在上面的例子中,渲染了一張寬度為視窗寬度一半(sizes="50vw")的圖像,根據瀏覽器的寬度及其設備像素比,允許瀏覽器選擇正確的圖像,而不考慮瀏覽器窗口有多大。

上面我們看到的僅是srcsetsizes屬性的冰山一角,有關於更詳細的東西我們不在這裡闡述,如果你感興趣的話,可以觀注後續的更新,因為我最近正在探討如何藉助這兩個特性在移動端不同的設備上載入所需要的圖像資源。

在HTML5中新增了一個元素標籤:<picture>。該元素可以通過若干個<source>,而且瀏覽器會自動匹配<source>typemediasrcset等屬性,來找到最適合當前佈局、視窗寬度、設備像素密度的圖像資源。其次在該元素裡面還可以內嵌一個img標籤,用來作為其降級處理,一旦瀏覽器不支持picture元素,會自動引入內嵌的img引入的圖片。比如下面這個示例:

<picture> <source media="(min-width: 800px)" srcset="head.jpg, head-2x.jpg 2x"> <source media="(min-width: 450px)" srcset="head-small.jpg, head-small-2x.jpg 2x"> <img src="head-fb.jpg" srcset="head-fb-2x.jpg 2x" alt="a head carved out of wood"></picture>

上面的例子中,如果瀏覽器寬度至少為 800px,則將根據設備解析度使用 head.jpghead-2x.jpg。如果瀏覽器寬度在 450px800px 之間,則將根據設備解析度使用 head-small.jpghead-small-2x.jpg。對於屏幕寬度小於 450px,且不支持 picture 元素向後兼容的情況,瀏覽器將渲染 img 元素,因此要始終包含該元素。

是不是看上去picture有點類似於具備了srcsetsizes屬性的img

CSS引入圖片

除了熟悉的img元素之外,在Web上還有另一種大家熟悉的方式是通過CSS的background-image屬性來引入圖片。其使用方式非常的簡單:

.logo { background-image: url(logo.png);}

該屬性除了可以給一個元素設置一個背景圖像之外,還可以通過用逗號隔開引用多個url(),給元素設置多個背景圖像。圖像在繪製時,以z軸方向堆疊的方式進行。先指定的圖像會在之後指的圖像上面繪製。因此指定的第一個圖像最接近用戶。

在CSS中我們可以通過一些相關的屬性來控制background-image引入的圖像的展示方式。比如background-positionbackground-repeatbackground-sizebackground-clip等。除此之外,還可以使用CSS的混合模式屬性,比如background-blend-mode處理一些特殊效果。

在CSS中除background-image之外,CSS Images Module Level 4提供了一個image-set()函數,可以幫助我們根據不同的dpr顯示不同的圖像:

.logo { background-image: image-set(url([email protected]) 1x,url([email protected]) 2x);}

當然,也可以在image-set()前面引入正常使用background-image的方式,給image-set()做降級處理:

.logo { background-image: image-set(url([email protected]); background-image: image-set(url([email protected]) 1x,url([email protected]) 2x);}

在HTML中的img或者picture元素,我們可以通過srcsetsizes等特性為不同的狀態(比如不同的視窗寬度)載入不同的圖像。時至今日,CSS可以藉助媒體查詢特性,顯示不同的圖像。比如媒體查詢根據設備像素比規則,讓你實現類似image-set()的特性,針對2x1x顯示不同的圖像。

@media (min-resolution: 2dppx),(-webkit-min-device-pixel-ratio: 2){ .logo { background-image: url([email protected]) }}

Chrome、Firefox 和 Opera 都支持標準的 (min-resolution: 2dppx),Safari 和 Android 瀏覽器則均需要不帶 dppx 單位的舊版供應商前綴語法。請謹記,這些樣式只有在設備與媒體查詢匹配時才被載入,且必須為基礎案例指定樣式。 這樣也能夠確保當瀏覽器不支持解析度特有的媒體查詢時,一些內容仍可以得到渲染。

.logo { background-image: url([email protected]);}@media (min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 2) { .logo { background-image: url([email protected]); }}

您也可以使用 min-width(或max-width) 語法根據視口大小顯示備用圖像。 此方法的好處是,如果媒體查詢不匹配,則圖像不會被下載。 例如,只有在瀏覽器寬度等於 500px 或更大時,bg.png 才會被下載,然後應用於 body

@media (min-width: 500px) { body { background-image: url(bg.png); }}

圖像處理方式

這裡所說的圖像處理方式並不像圖像處理軟體中一樣的處理圖像。這裡所說的處理方式主要指的是圖像樣式的處理,其涵蓋:效果處理和適配處理兩個部分。

圖像的效果處理

先不管是哪種方式引入的圖像,在Web上總是會遇到圖像效果的處理。最直接的,比如說處理圖像的尺寸。在img中我們可以使用該元素自備的屬性widthheight來處理。當然也可以通過CSS的widthheightmax-width/heightmin-width/hegiht來處理。但要處理尺寸之外的一些效果,我們就只能通過CSS的屬性來處理。

到目前為止,通過CSS來處理圖像的效果只要有CSS的 混合模式濾鏡相關的屬性。對於imgpicture元素引入的圖像,可以使用mix-blend-modefilter。比如下面這個mix-blend-mode處理的圖像效果:

再來看一看filter處理圖像的效果,@una寫的一個 CSS濾鏡工具:

事實上,filter不僅僅可以用於img上,還可以運用於任何的HTML元素上。另外,在CSS濾鏡規範中還提供了一些高級濾鏡的屬性,比如backdrop-filterfilter()屬性,這些屬性可以幫助我們實現一些更特殊的效果,比如iOS上的毛玻璃效果:

除此之外,CSS的混合模式的另一屬性background-blend-mode常用於使用了背景圖像的元素上,達到處理圖像的效果:

@bennettfeely在Codepen上寫了一個很優秀的Demo:

如果你覺得CSS的混合模式和濾鏡很強大,希望深入的去探索相關的知識,建議你花點時間閱讀下面相關的教程:

  • CSS混合模式高級應用
  • Compositing And Blending In CSS
  • CSS 混合模式
  • CSS3 Filter的十種特效
  • 高級CSS filters

上面我們看到的是CSS混合模式和濾鏡怎麼處理圖像,但有的時候我們需要有一些特殊形狀之類的效果,那麼此時就需要CSS Masking Module Level 1提供的mask-*clip-path屬性。比如這樣的效果:

上圖是使用mask-image實現的一個效果。clip-path就更強大了:

有關於CSS maskclip-path效果,可以在Codepen上找到很多優秀案例。除了案例,互聯網上優秀的教程也不少:

  • CSS Masking
  • CSS中的剪裁和遮罩
  • 如何在CSS中使用遮罩
  • CSS Masking
  • Shapes in clipping and masking – and how to use them
  • Clipping and Masking in CSS
  • Cropping & Scaling Images Using SVG Documents
  • ref="w3cplus.com/blog/tags/4">CSS clip-path
  • Using CSS Clip Path to Create Interactive Effects:Part1 and Part2
  • Introduction to Clipping Using clip-path in CSS

圖像適配

圖像適配估計讓不少的同學頭痛和蛋疼,特別是面對移動端開發的時候。在我的印象中,第一次接觸圖像適配的處理是在做響應式網站的時候。自從有了響應式網站設計,那麼對於圖像的處理,也有一個對應的專業術語:Responsive Image,對於響應式圖像的處理也有很多優秀的文章:

  • Responsive Images 101 (譯文)
  • Responsive Images 201: Client Hints
  • A Guide to Responsive Images with Ready-to-Use Templates
  • Responsive Images with srcset
  • ef="https://www.zhangxinxu.com/wordpress/2014/10/responsive-images-srcset-size-w-descriptor/">響應式圖片srcset全新釋義sizes屬性w描述符
  • HTML5響應式圖片技術中文圖解
  • 實戰響應式圖片
  • Fundamentals of Responsive Images
  • Building a responsive image
  • Responsive images

雖然響應式圖像很強大,但我們平時面對的還是要想辦法怎麼靈活的處理圖像。針對於這方面,我更喜歡把這些稱為Flexible Images。而且平時也經常碰到同學會問,怎麼讓圖像能更適合或適配容器,比如最常見的全屏圖像這樣的效果。

時至今日,靈活處理圖像有很多種方式,老舊一點的方案是使用max-width

img { max-width: 100%;}

讓一張img能較為靈活的適合容器。先進一點的是object-fit這樣的屬性,讓你的圖像能較靈活的適配容器:

感興趣的同學,可以在下面的Demo體驗一下下:

object-fit &amp; object-position?

codepen.io
圖標

前面提到過,引入圖像除了img還有background-image,那麼在CSS中還有一個background-size屬性類似於object-fit屬性,可以幫助靈活的處理背景圖像適配元素尺寸。

有關於Flexible Images更詳細的介紹,可以閱讀早期整理的相關文章《Flexible Images》。

另外一個場景是,圖像能根據容器的長寬比來顯示:

在WICG的討論上,有人提出來了原生的長寬比屬性aspect-ratio。例如,給定一個容器元素它的widthheight都設置為auto,並且aspect-ratio的值為2/1max-height:200px。一個容器寬度為500px時,元素首先會設置width:500px,然後根據aspect-ratio比例將height設置為250px。這個時候其實違反了max-height的約束。相反,容器大小會變成height: 200pxwidth:400px。另外,如果元素的max-width是450px時,長寬比將會完全被忽視,因為無法滿足。

這是未來的一個CSS屬性,雖然離我們很遠,但慶幸的是,有很多替代方案可以實現,最常見的就是padding來模擬:

.aspectration { position: relative; /*因為容器所有子元素需要絕對定位*/ height: 0; /*容器高度是由padding來控制,盒模型原理告訴你一切*/ width: 100%; } .aspectration[data-ratio="16:9"] { padding-top: 56.25%; } .aspectration[data-ratio="4:3"]{ padding-top: 75%; }

如果你要走時髦的話,你可以使用CSS自定義屬性、calc()vw,甚至CSS的Grid。我們來看其中一個示例吧:

CSS Aspect Ratios, Technique #1b?

codepen.io
圖標

有關於其他的方案或更詳細的介紹,可以花點時間閱讀下面的文章:

  • 容器長寬比
  • CSS實現長寬比的幾種方案
  • Web中如何實現縱橫比
  • Flexible Images
  • Aspect Ratios in CSS are a Hack
  • Aspect Ratio Calculator

Web圖片載入與渲染規則

前面我們花費了不少的篇幅介紹了Web中怎麼載入圖片,如何處理圖片以及圖片的適配。除了關注這幾點之外,我們還應該關注圖片載入與渲染的規則,因為只有掌握了這些才能更好的理解Web圖像的運用。也能給用戶更好的體驗。那麼接下來,咱們將花一點時間來瞭解一下圖片載入和渲染規則。

如果要對圖片載入和渲染規則有較好的理解,就需要具備一些基礎知識,比如說瀏覽器的工作原理。不過這部分已經超出這篇文章的範圍,如果你感興趣,可以花一些時間閱讀下面幾篇文章:

  • 瀏覽器的工作原理:新式網路瀏覽器幕後揭祕
  • 瀏覽器的渲染原理簡介
  • 瀏覽器內核、JS 引擎、頁面呈現原理及其優化
  • 聊聊 JavaScript 與瀏覽器的那些事:引擎與線程
  • 瀏覽器渲染過程與性能優化
  • Web 性能優化:頁面重繪和迴流
  • 從瀏覽器輸入一個 URL 到頁面渲染
  • 從輸入URL到頁面載入發生了什麼?

如果你閱讀完上面這些文章,我相信你對瀏覽器渲染的工作原理有所瞭解,那麼後續的內容就不會有什麼難度了。

先上一張圖:

Web瀏覽器先會把獲取到的HTML代碼解析成一個DOM樹,HTML中的每個標籤都是DOM樹中的一個節點,包括display: none隱藏的標籤,還有JavaScript動態添加的元素等。瀏覽器會獲取到所有樣式,並會把所有樣式解析成樣式規則,在解析的過程中會去掉瀏覽器不能識別的樣式。

瀏覽器將會把DOM樹和樣式規則組合在一起(DOM元素和樣式規則匹配)後將會合建一個渲染樹(Render Tree),渲染樹類似於DOM樹,但兩者別還是很大的:渲染樹能識別樣式,渲染樹中每個節點(NODE)都有自己的樣式,而且渲染樹不包含隱藏的節點(比如display:none的節點,還有</head>內的一些節點),因為這些節點不會用於渲染,也不會影響節點的渲染,因此不會包含到渲染樹中。一旦渲染樹構建完畢後,瀏覽器就可以根據渲染樹來繪製頁面了。

簡單的歸納就是瀏覽器渲染Web頁面大約會經過六個過程:

  • 解析HTML,構成DOM樹
  • 解析載入的樣式,構建樣式規則樹
  • 載入JavaScript,執行JavaScript代碼
  • DOM樹和樣式規則樹進行匹配,構成渲染樹
  • 計算元素位置進行頁面佈局
  • 繪製頁面,最終在瀏覽器中呈現

是不是會感覺這個和我們圖像載入渲染沒啥關係一樣,事實並非如此,因為imgpicture或者background-image都是DOM樹或樣式規則中的一部分,那麼咱們套用進來,圖片載入和渲染的時機有可能是下面這樣:

  • 解析HTML時,如果遇到imgpicture標籤,將會載入圖片
  • 解析載入的樣式,遇到background-image時,並不會載入圖片,而會構建樣式規則樹
  • 載入JavaScript,執行JavaScript代碼,如果代碼中有創建img元素之類,會添加到DOM樹中;如查有添加background-image規則,將會添加到樣式規則樹中
  • DOM樹和樣式規則匹配時構建渲染樹,如果DOM樹節點匹配到樣式規則中的backgorund-image,則會載入背景圖片
  • 計算元素(圖片)位置進行佈局
  • 開始渲染圖片,瀏覽器將呈現渲染出來的圖片

上面套用瀏覽器渲染頁面的機制,但圖片載入與渲染還是有一定的規則。因為,頁面中不是所有的<img>(或picture)元素引入的圖片和background-image引入的背景圖片都會載入的。那麼就引發出新問題了,什麼時候會真正的載入,載入規則又是什麼?

先概括一點:

Web頁面中不是所有的圖片都會載入和渲染

根據前面介紹的瀏覽器載入和渲染機制,我們可以歸納為:

  • <img><picture>和設置background-image的元素遇到display:none時,圖片會載入但不會渲染
  • <img><picture>和設置background-image的元素祖先元素設置display:none時,background-image不會渲染也不會載入,而imgpicture引入的圖片不會渲染但會載入
  • <img><picture>background-image引入相同路徑相同圖片文件名時,圖片只會載入一次
  • 樣式文件中background-image引入的圖片,如果匹配不到DOM元素,圖片不會載入
  • 偽類引入的background-image,比如:hover,只有當偽類被觸發時,圖片才會載入

感興趣的同學,不仿自己寫寫Demo驗證一下。

Web圖像優化

Web圖像通常佔據了網頁上下載位元組的大部分,通常也佔據了大量的視覺空間。因此,優化圖像通常可以最大限度地減少下載的位元組數以及提高網站性能:瀏覽器需要下載的位元組越少,佔用客戶端的帶寬就越少,瀏覽器下載並在屏幕上渲染有用內容的速度就越快。

圖像優化既是一門藝術,也是一門科學:說它是一門藝術,是因為單個圖像的壓縮並不存在明確的最佳方案,說它是一門科學,則是因為有許多發展成熟的方法和演算法都能夠顯著縮減圖像的大小。找到圖像的最佳設置需要在許多方面進行認真分析:格式能力、編碼數據的內容、質量、像素尺寸等。

@Ilya Grigorik在《圖像優化》一文中做了詳細的介紹。下面幾點是他給大家做圖片優化時提供的參考意見:

  • 首選矢量格式:矢量圖像與解析度和縮放無關,這使它們成為多設備和高解析度情況的完美選擇。
  • 縮小和壓縮 SVG 資產: 大多數繪圖應用程序生成的 XML 標記往往包含可以移除的多餘元數據;確保您的伺服器配置為對 SVG 資產採用 GZIP 壓縮。
  • 挑選最佳光柵圖片格式:確定您的功能要求並選擇適合每個特定資產的格式。
  • 通過試驗為光柵格式找到最佳質量設置:不要害怕調低「質量」設置,調低後的效果通常很不錯,並且位元組數的縮減很顯著。
  • 移除多餘的圖像元數據:許多光柵圖像都包含多餘的資產元數據:地理信息、相機信息等。請使用合適的工具刪除這些數據。
  • 提供縮放的圖像:調整伺服器上的圖像尺寸,並確保圖像的「顯示」尺寸儘可能接近其「自然」尺寸。尤其要密切注意較大的圖像,因為在調整尺寸時,它們佔用的開銷最大!
  • 自動化、自動化、自動化:投資購置自動化工具和基礎設施,這樣可以確保您的所有圖像資產始終得到優化。

結論

Web圖片在Web中已經是很重要的一部分,理解或掌握了怎麼在Web中使用圖片是很重要的。可以讓你的網站更具有體驗性,或者從利益上說,他直接可以幫助你省不少銀子。這篇文章,從怎麼引入Web圖片方式入手,以及如何處理圖片,優化圖片,甚至從瀏覽器的載入和渲染機制的基礎上進行更深一步的判斷,在實際使用中如何選擇。比如是使用imgpicture還是background-image。當然,使用圖片不僅僅這些東西,涉及到的方方面面還是很多,只有徹底瞭解清楚這些東西,你才能更好的使用好圖片。如果你感興趣,不仿花一些時間閱讀閱讀《Images guide》一文。 我想你會喜歡上這篇指南的。

如需轉載,煩請註明出處:w3cplus.com/css/how-to-

推薦閱讀:

相關文章