【學習圖片】12.規定性的語法

前端小智發表於2023-03-09
本文首發於微信公眾號:大遷世界, 我的微信:qq449245884,我會第一時間和你分享前端行業趨勢,學習途徑等等。
更多開源作品請看 GitHub https://github.com/qq449245884/xiaozhi ,包含一線大廠面試完整考點、資料以及我的系列文章。

瞭解一下 picture 元素。

<picture>元素本身不會渲染任何內容,而是作為內部<img>元素的決策引擎,告訴它應該渲染什麼。<picture>遵循了<audio><video>元素已經設定的先例:一個包含單獨<source>元素的包裝器元素。

<picture>
   <source …>
   <source …>
    <img …>
</picture …>

那個內部的<img>元素也為我們提供了一個可靠的回退模式,用於不支援響應式圖片的舊瀏覽器:如果使用者的瀏覽器不識別<picture>元素,它將被忽略。然後,<source>元素也將被丟棄,因為瀏覽器要麼根本不識別它們,然而,內部的<img>元素將被任何瀏覽器識別,而其src屬性指定的源將如預期地渲染。

art directed 與 <picture>

根據影像在頁面中的大小進行內容或縱橫比的更改,通常被稱為“art directed” 響應式影像 。srcsetsizes旨在無縫地工作,根據使用者瀏覽器的指示無縫地交換源。然而,有時我們希望在斷點處更改源以更好地突出內容,就像調整頁面佈局一樣。例如:在大視口上,帶有小中央焦點的全寬頭影像可能效果很好:

image.png

但是,當縮小以適應小視口時,影像的中央焦點可能會丟失:

一張縮小了的遠古藍色花卉的頭部影像。蜜蜂幾乎看不見。

這些影像源的主題相同,但為了更好地視覺聚焦於該主題,我們將希望影像源的比例在斷點處發生變化。例如,對影像中心進行更緊密的縮放,並剪下掉一些邊緣的細節:

image.png

這種“剪下”可以透過CSS實現,但會使使用者請求組成該影像的所有資料,即使他們可能永遠不會看到它。

每個 source 元素都有定義選擇該源的條件的source: media,它接受媒體查詢,以及型別,它接受媒體型別(以前稱為“MIME型別”)。在源順序中與使用者當前瀏覽上下文匹配的第一個<source>將被選擇,並且該源的srcset屬性的內容將用於確定該上下文的正確候選項。在此示例中,第一個具有與使用者視口大小匹配的 media 屬性的源將被選中:

<picture>
  <source media="(min-width: 1200px)" srcset="wide-crop.jpg">
  <img src="close-crop.jpg" alt="…">
</picture>

地址:

https://codepen.io/web-dot-dev/pen/poZNxyN

我們應該始終在順序中指定內部img的最後一個——如果沒有一個<source>元素與其mediatype 條件匹配,該影像將充當“預設”源。如果你使用min-width媒體查詢,則應首先使用最大的源,如前面的程式碼所示。當使用max-width媒體查詢時,應該將最小的源放在第一位。

<picture>
   <source media="(max-width: 400px)" srcset="mid-bp.jpg">
   <source media="(max-width: 800px)" srcset="high-bp.jpg">
   <img src="highest-bp.jpg" alt="…">
</picture>

當根據指定的條件選擇源時,<source>上的srcset屬性會傳遞給<img>,就像它是在<img>本身上定義的一樣——這意味著我們可以使用sizes來最佳化"art directed"影像源。

<picture>
   <source media="(min-width: 800px)" srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w">
   <source srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w">
   <img src="fallback.jpg" alt="…" sizes="calc(100vw - 2em)">
</picture>

當然,一個影像的比例可能會因所選的<source>元素而異,這會帶來效能問題:<img>只支援單個寬度和高度屬性,但省略這些屬性會導致使用者體驗明顯變差。為了解決這個問題,HTML規範的一個相對較新但得到很好支援的補充允許在<source>元素上使用高度和寬度屬性。這些屬性的作用與在<img>上的作用一樣,可以很好地減少佈局移位,為所選的任何<source>元素在佈局中預留適當的空間。

<picture>
   <source
      media="(min-width: 800px)"
      srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w"
      width="1600"
      height="800">
   <img src="fallback.jpg"
      srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w"
      sizes="calc(100vw - 2em)"
      width="1200"
      height="750"
      alt="…">
</picture>

需要注意的是,"art direction"不僅僅可以用於基於視口大小的決策,而且應該使用,因為在大多數情況下,這些情況可以透過srcset / sizes更有效地處理。例如,選擇更適合使用者偏好指定的顏色方案的影像源:

<picture>
   <source media="(prefers-color-scheme: dark)" srcset="hero-dark.jpg">
   <img srcset="hero-light.jpg">
</picture>

示例地址:https://codepen.io/web-dot-dev/pen/MWBbPJm

type 屬性

type屬性允許我們使用<picture>元素的單請求決策引擎,僅向支援它們的瀏覽器提供影像格式。

正如在“影像格式和壓縮”中學到的那樣,瀏覽器無法解析的編碼甚至都不會被識別為影像資料。

在引入<picture>元素之前,為了提供新的影像格式,最可行的前端解決方案需要瀏覽器請求並嘗試解析影像檔案,然後確定是否將其丟棄並載入回退。一個常見的例子是:

<img src="image.webp"
  data-fallback="image.jpg"
  onerror="this.src=this.getAttribute('data-fallback'); this.onerror=null;"
  alt="...">

使用這種模式,仍然會在每個瀏覽器中請求image.webp,這意味著在不支援WebP的瀏覽器中浪費了傳輸。無法解析WebP編碼的瀏覽器將引發onerror事件,並將data-fallback值交換到src。這是一種浪費的解決方案,但是,像這樣的方法是前端上唯一可用的選項。請記住,瀏覽器在任何自定義指令碼有機會執行或甚至被解析之前開始請求影像,因此我們無法預先防止這個過程。

<picture>元素的設計明確旨在避免這些冗餘請求。雖然沒有辦法讓瀏覽器在不請求的情況下識別它不支援的格式,但type屬性提前警告瀏覽器有關源編碼的資訊,因此可以決定是否進行請求。

type屬性中,我們提供每個<source>元素的srcset屬性中指定的影像源的媒體型別(以前是MIME型別)。這為瀏覽器提供了所有所需的資訊,以立即確定該<source>提供的影像候選項是否可以解碼而無需進行任何外部請求——如果媒體型別未被識別,則<source>及其所有候選項都將被忽略,並且瀏覽器將繼續執行。

<picture>
 <source type="image/webp" srcset="pic.webp">
 <img src="pic.jpg" alt="...">
</picture>

在這裡,任何支援WebP編碼的瀏覽器都將識別<source>元素的type屬性中指定的image/webp媒體型別,選擇該<source>元素,並且由於我們只在srcset中提供了一個候選項,因此指示內部<img>請求、傳輸和渲染 pic.webp

任何不支援WebP的瀏覽器將忽略該源,如果沒有任何相反的指示,<img>將像自1992年以來一樣渲染src的內容。當然,在這裡不需要指定第二個type="image/jpeg"<source>元素——可以假設所有瀏覽器都支援JPEG。

無論使用者的瀏覽上下文如何,這一切都透過單個檔案傳輸實現,而不會浪費頻寬在不能呈現的影像源上。這也是前瞻性的:隨著更新更高效的檔案格式將帶有自己的媒體型別,我們將能夠藉助picture利用它們——無需JavaScript、無伺服器依賴,並且具有<img>的所有速度。

響應式影像的未

在這裡討論的所有標記模式在標準化方面都是一個巨大的挑戰:改變像<img>這樣已經成為Web核心的東西的功能不是一件小事,而這些變化旨在解決的問題集也是相當廣泛的。如果你發現自己認為這些標記模式有很大的改進空間,那麼你是完全正確的。從一開始,這些標準就旨在為未來的技術提供基準。

所有這些解決方案都必須依賴標記,以便包含在伺服器的初始負載中,並及時到達瀏覽器請求影像源,這一限制導致了明顯笨重的sizes屬性。

然而,自從這些特性被引入到Web平臺以來,就引入了一種延遲影像請求的本地方法。具有loading="lazy"屬性的<img>元素直到頁面佈局已知才被請求,以便推遲對使用者初始視口之外的影像的請求,直到在渲染頁面的過程中稍後進行,從而避免不必要的請求。因為瀏覽器在這些請求發出時完全瞭解頁面佈局,因此已經提出了一個sizes="auto"屬性作為HTML規範的附加內容,在這些情況下避免手動編寫sizes屬性的繁瑣工作。

此外,<picture> 元素也即將有一些新的改進,以匹配頁面佈局樣式方面的一些極其令人興奮的變化。雖然基於視口資訊的高階佈局決策是可靠的,但它阻止了我們採用完全基於元件層級的開發方法,這意味著可以將元件放置在頁面佈局的任何部分,並響應元件本身所佔用的空間的樣式。這種情況促使出現了容器查詢:一種基於父容器大小而非視口大小來為元素設定樣式的方法。

雖然容器查詢語法才剛剛穩定下來,而且在撰寫本文時,瀏覽器支援非常有限,但啟用它的瀏覽器技術的增加將為 <picture> 元素提供同樣的方法:一種潛在的容器屬性,它允許基於 <picture> 元素的 <img> 所佔用的空間而非基於視口大小來選擇 <source>

如果聽起來有點模糊,那麼這是有很好的原因的:這些 Web 標準的討論仍在進行中,遠未定案,目前還不能使用它們。

雖然響應式圖片標記承諾隨著時間的推移只會變得更易於使用,但像任何 Web 技術一樣,有許多服務、技術和框架可用於幫助減輕手寫此標記的負擔。在下一個模組中,我們將學習如何將我們所學的有關影像格式、壓縮和響應式圖片的所有內容整合到現代開發工作流程中。

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章