響應式圖片

在本文中,我們將學習響應式圖片的概念——在螢幕尺寸、解析度和其他功能差異很大的裝置上都能良好顯示的圖片——並瞭解 HTML 提供的哪些工具可以幫助實現它們。這有助於提高不同裝置上的效能。響應式圖片只是 響應式設計 的一部分,這是您將來要學習的 CSS 主題。

先決條件 您應該已經瞭解 HTML 基礎 以及如何 向網頁新增靜態影像
目標 學習如何使用 srcset<picture> 元素等功能在網站上實現響應式影像解決方案。

為什麼需要響應式圖片?

讓我們來看一個典型的場景。一個典型的網站可能包含一個標題影像和標題下方的一些內容影像。標題影像可能會橫跨標題的整個寬度,內容影像將適合內容列中的某個位置。這是一個簡單的示例

Our example site as viewed on a wide screen - here the first image works OK, as it is big enough to see the detail in the center.

這在寬屏裝置(例如筆記型電腦或桌上型電腦)上效果很好(您可以 檢視示例 並找到 GitHub 上的 原始碼)。在本課中,我們不會過多討論 CSS,只是說

  • 主體內容的最大寬度設定為 1200 畫素——在超過該寬度的視口中,主體保持 1200px 並居中顯示在可用空間中。在低於該寬度的視口中,主體將保持視口寬度的 100%。
  • 標題影像的設定使得無論標題的寬度設定為多少,其中心始終保持在標題的中心。如果網站在較窄的螢幕上檢視,則影像中心的重要細節(人物)仍然可見,多餘的部分則會丟失在兩側。它的高度為 200px。
  • 內容影像的設定使得如果主體元素變得小於影像,則影像開始縮小,以便始終保持在主體內部,而不是溢位主體。

但是,當您開始在窄屏裝置上檢視網站時,就會出現問題。下面的標題看起來還可以,但它開始佔據移動裝置大量螢幕高度。而且在這個尺寸下,很難看清第一個內容影像中兩個人的臉。

Our example site as viewed on a narrow screen; the first image has shrunk to the point where it is hard to make out the detail on it.

改進的方法是在網站在窄屏上檢視時,顯示影像的裁剪版本,顯示影像的重要細節。可以在平板電腦等中等寬度螢幕裝置上顯示第二個裁剪影像。以這種方式為各種佈局提供不同裁剪影像的通用問題通常稱為藝術指導問題

此外,如果在移動裝置螢幕上檢視頁面,則無需在頁面上嵌入如此大的影像。這樣做會浪費頻寬;特別是,移動使用者不想浪費頻寬來下載專為桌面使用者設計的影像,而一個小影像足以滿足其裝置的需求。相反,當一個小型的光柵影像顯示尺寸大於其原始尺寸時,它會開始變得模糊(光柵影像的寬度和高度都是固定畫素數,我們在檢視向量圖形時已經看到了)。理想情況下,會向用戶的 Web 瀏覽器提供多種解析度。然後,瀏覽器可以根據使用者裝置的螢幕尺寸確定要載入的最佳解析度。這被稱為解析度切換問題

為了使事情變得更加複雜,某些裝置具有高解析度螢幕,需要比您預期的更大的影像才能很好地顯示。這本質上是相同的問題,但處於略微不同的上下文中。

您可能會認為向量影像可以解決這些問題,並且在某種程度上確實如此——它們的 檔案大小很小並且可以很好地縮放,並且您應該儘可能地使用它們。但是,它們不適用於所有影像型別。向量影像非常適合簡單的圖形、圖案、介面元素等,但是使用向量影像建立具有照片中那種細節的影像會變得非常複雜。JPEG 等光柵影像格式更適合我們在上述示例中看到的影像型別。

在 90 年代初期到中期,網路剛剛出現時,這種問題並不存在——當時唯一存在的用於瀏覽網路的裝置是桌上型電腦和筆記型電腦,因此瀏覽器工程師和規範編寫者甚至沒有考慮過實現解決方案。響應式影像技術最近被實施以解決上述問題,方法是允許您為瀏覽器提供多個影像檔案,這些檔案要麼都顯示相同的內容但包含不同數量的畫素(解析度切換),要麼是適合不同空間分配的不同影像(藝術指導)。

注意:本文討論的新功能——srcset/sizes/<picture>——都受現代桌面和移動瀏覽器支援。

如何建立響應式圖片?

在本節中,我們將研究上面說明的兩個問題,並展示如何使用 HTML 的響應式影像功能來解決它們。您應該注意,我們將重點關注本節中的<img>元素,如上例的內容區域所示——站點標題中的影像僅用於裝飾,因此使用 CSS 背景影像實現。CSS 在響應式設計方面擁有比 HTML 更好的工具,我們將在以後的 CSS 模組中討論這些工具。

解析度切換:不同尺寸

那麼,我們希望透過解析度切換解決什麼問題呢?我們希望顯示相同的影像內容,只是根據裝置的大小顯示更大或更小——這就是我們示例中第二個內容影像的情況。傳統的<img>元素通常只允許您將瀏覽器指向單個原始檔。

html
<img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy" />

但是,我們可以使用兩個屬性——srcsetsizes——來提供幾個額外的源影像以及幫助瀏覽器選擇合適的影像的提示。您可以在 GitHub 上的responsive.html示例中看到一個示例(另請參閱原始碼

html
<img
  srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w"
  sizes="(max-width: 600px) 480px,
         800px"
  src="elva-fairy-800w.jpg"
  alt="Elva dressed as a fairy" />

srcsetsizes屬性看起來很複雜,但是如果您像上面顯示的那樣格式化它們,每個屬性值都放在一行上,那麼它們並不難理解。每個值都包含一個逗號分隔的列表,這些列表的每個部分都由三個子部分組成。現在讓我們瀏覽一下每個部分的內容。

srcset定義了我們將允許瀏覽器從中選擇的影像集,以及每個影像的大小。每個影像資訊集都用逗號與前一個影像資訊集分隔開。對於每個影像資訊集,我們都會編寫

  1. 一個影像檔名elva-fairy-480w.jpg
  2. 一個空格
  3. 影像的固有寬度(以畫素為單位)480w)——請注意,這裡使用的是w單位,而不是您可能預期的px。影像的固有尺寸是其真實尺寸,可以透過檢查計算機上的影像檔案找到(例如,在 Mac 上,您可以選擇 Finder 中的影像並按Cmd + I調出資訊螢幕)。

sizes定義了一組媒體條件(例如螢幕寬度),並在某些媒體條件為真時指示選擇什麼影像尺寸最合適——這些是我們之前討論過的提示。在這種情況下,在每個逗號之前,我們都會編寫

  1. 一個媒體條件(max-width:600px))——您將在CSS 主題中瞭解更多關於這些內容,但現在讓我們假設媒體條件描述了螢幕可能處於的某個狀態。在這種情況下,我們說的是“當視口寬度為 600 畫素或更小時”。
  2. 一個空格
  3. 媒體條件為真時影像將填充的插槽寬度480px

注意:sizes中,您可以使用任何長度值。例如,您可以提供相對於視口的寬度(例如50vw),而不是提供絕對寬度(例如480px)。但是,您不能使用百分比作為插槽寬度。您可能已經注意到,最後一個插槽寬度沒有媒體條件(這是在沒有媒體條件為真的情況下選擇的預設值)。瀏覽器會忽略第一個匹配條件之後的所有內容,因此請注意媒體條件的順序。

因此,有了這些屬性,瀏覽器將

  1. 檢視螢幕尺寸、畫素密度、縮放級別、螢幕方向和網路速度。
  2. 確定sizes列表中哪個媒體條件是第一個為真的條件。
  3. 檢視給定媒體查詢的插槽大小。
  4. 載入srcset列表中與插槽大小相同的影像,或者如果沒有,則載入第一個大於所選插槽大小的影像。

就是這樣!此時,如果具有 480px 視口寬度的支援瀏覽器載入頁面,則(max-width: 600px)媒體條件將為真,因此瀏覽器會選擇480px插槽。elva-fairy-480w.jpg將被載入,因為其固有寬度(480w)最接近插槽大小。800 畫素的圖片在磁碟上的大小為 128KB,而 480 畫素的版本僅為 63KB——節省了 65KB。現在,想象一下如果這是一個頁面上有許多圖片的頁面。使用此技術可以為移動使用者節省大量頻寬。

注意:在使用桌面瀏覽器進行測試時,如果瀏覽器在將視窗設定為最窄寬度時未能載入較窄的影像,請檢視視口是什麼(您可以透過進入瀏覽器的 JavaScript 控制檯並輸入document.querySelector('html').clientWidth來估算它)。不同的瀏覽器有它們允許您將視窗寬度縮小到的最小尺寸,並且它們可能比您想象的要寬。在使用移動瀏覽器進行測試時,您可以使用 Firefox 的about:debugging頁面等工具使用桌面開發者工具檢查在移動裝置上載入的頁面。

要檢視載入了哪些影像,您可以使用 Firefox DevTools 的網路監視器選項卡或 Chrome DevTools 的網路面板。對於 Chrome,您可能還需要停用快取以防止它選擇已下載的影像。

不支援這些功能的舊版瀏覽器將忽略它們。相反,這些瀏覽器將繼續載入src屬性中引用的影像,就像平常一樣。

注意:在上面連結的示例的<head>中,您會找到<meta name="viewport" content="width=device-width">這一行:這會強制移動瀏覽器採用其真實的視口寬度來載入網頁(一些移動瀏覽器會虛報其視口寬度,而是以更大的視口寬度載入頁面,然後將載入的頁面縮小,這對響應式影像或設計幫助不大)。

解析度切換:相同尺寸,不同解析度

假設您有一個影像,它將在具有不同螢幕解析度的顯示器上以相同的真實世界尺寸呈現。您可以透過提供更高解析度版本的影像,在高解析度顯示器上提供更好的使用者體驗。

為了實現這一點,您可以使用帶 x 描述符但不帶sizessrcset允許瀏覽器選擇適當的解析度影像——這是一種稍微簡單的語法!您可以在srcset-resolutions.html中找到一個示例(另請參閱原始碼

html
<img
  srcset="elva-fairy-320w.jpg, elva-fairy-480w.jpg 1.5x, elva-fairy-640w.jpg 2x"
  src="elva-fairy-640w.jpg"
  alt="Elva dressed as a fairy" />

請注意,即使影像始終以相同的大小顯示,在高解析度顯示器上,您也可以看到更多細節。

A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the image

在此示例中,以下 CSS 應用於影像,以便它在螢幕上(也稱為 CSS 畫素)的寬度為 320 畫素。

css
img {
  width: 320px;
}

在這種情況下,不需要sizes——瀏覽器會計算出顯示器正在使用的解析度,並提供srcset中引用的最合適的影像。因此,如果訪問頁面的裝置具有標準/低解析度顯示器,其中一個裝置畫素代表每個 CSS 畫素,則將載入elva-fairy-320w.jpg影像(1x 是隱含的,因此您無需包含它)。如果裝置具有高解析度,每個 CSS 畫素有兩個或更多裝置畫素,則將載入elva-fairy-640w.jpg影像。640 畫素的影像為 93KB,而 320 畫素的影像僅為 39KB。

藝術指導

概括地說,藝術指導問題涉及希望更改顯示的影像以適應不同的影像顯示尺寸。例如,網頁在桌面瀏覽器上檢視時包含一箇中間有人物的大型橫向照片。在移動瀏覽器上檢視時,同一影像會縮小,使影像中的人物變得非常小且難以看到。在移動裝置上顯示較小的縱向影像可能更好,該影像會放大人物。<picture>元素允許我們實現這種型別的解決方案。

回到我們最初的not-responsive.html示例,我們有一個非常需要藝術指導的影像。

html
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva" />

讓我們用<picture>來修復它!與<video><audio>一樣,<picture>元素是一個包裝器,包含多個<source>元素,這些元素為瀏覽器提供了多個源以供選擇,然後是至關重要的<img>元素。responsive.html中的程式碼如下所示。

html
<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>
  • <source>元素包含一個media屬性,該屬性包含一個媒體條件——與第一個srcset示例一樣,這些條件是決定顯示哪個影像的測試——第一個返回 true 的影像將被顯示。在這種情況下,如果視口寬度為 799 畫素或更小,則將顯示第一個<source>元素的影像。如果視口寬度為 800 畫素或更大,則將顯示第二個元素的影像。
  • srcset屬性包含要顯示的影像的路徑。就像我們在上面看到的<img>一樣,<source>可以採用srcset屬性,其中引用了多個影像,以及sizes屬性。因此,您可以透過<picture>元素提供多個影像,然後也為每個影像提供多個解析度。實際上,您可能不會經常想要做這種事情。
  • 在所有情況下,您都必須在</picture>之前提供一個帶有srcalt<img>元素,否則將不會顯示任何影像。這提供了一個預設情況,當沒有媒體條件返回 true 時將應用此情況(您實際上可以從此示例中刪除第二個<source>元素),以及不支援<picture>元素的瀏覽器的後備方案。

此程式碼允許我們在寬屏和窄屏顯示器上顯示合適的影像,如下所示。

Our example site as viewed on a wide screen - here the first image works OK, as it is big enough to see the detail in the center. Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen

注意:您應該僅在藝術指導場景中使用media屬性;當您使用media時,不要在sizes屬性中也提供媒體條件。

為什麼我們不能只使用 CSS 或 JavaScript 來做到這一點?

當瀏覽器開始載入頁面時,它會開始下載(預載入)任何影像,然後主解析器才開始載入和解釋頁面的 CSS 和 JavaScript。該機制通常用於減少頁面載入時間,但對響應式影像沒有幫助——因此需要實現像srcset這樣的解決方案。例如,您不能載入<img>元素,然後使用 JavaScript 檢測視口寬度,然後根據需要動態地將源影像更改為較小的影像。到那時,原始影像已經載入,您還將載入小影像,這在響應式影像方面甚至更糟糕。

主動學習:實現您自己的響應式圖片

對於此主動學習,我們希望您勇敢地獨自完成,主要由您自己完成。我們希望您使用<picture>實現您自己的合適的藝術指導窄屏/寬屏截圖,以及使用srcset的解析度切換示例。

  1. 編寫一些簡單的 HTML 來包含您的程式碼(如果需要,可以使用not-responsive.html作為起點)。
  2. 找到一個漂亮的寬屏橫向影像,其中包含某種細節。使用圖形編輯器建立該影像的網頁版本,然後裁剪它以顯示放大細節的較小部分,並建立第二個影像(大約 480 畫素寬適合此)。
  3. 使用<picture>元素實現藝術指導圖片切換器!
  4. 建立多個不同尺寸的影像檔案,每個檔案都顯示相同的圖片。
  5. 使用srcset/sizes建立解析度切換器示例,或者根據裝置解析度提供相同尺寸影像的不同解析度,或者根據視口寬度提供不同影像尺寸。

總結

響應式影像到此結束——我們希望您喜歡嘗試這些新技術。作為回顧,我們在這裡討論了兩個不同的問題。

  • 藝術指導:您希望為不同的佈局提供裁剪影像的問題——例如,橫向影像為桌面佈局顯示完整場景,縱向影像為移動佈局顯示放大的主要主題。您可以使用<picture>元素解決此問題。
  • 解析度切換:當您希望為窄屏裝置提供更小的影像檔案時,就會遇到這個問題,因為它們不需要像桌面顯示器那樣的大影像——以及為高密度/低密度螢幕提供不同解析度的影像。您可以使用向量圖形(SVG 影像)以及帶有srcsetsizes屬性的srcset來解決此問題。

這也標誌著整個多媒體和嵌入模組的結束!現在,在繼續學習之前,您只需要嘗試我們的多媒體和嵌入評估,看看您的學習成果。祝您玩得開心!

另請參閱