HTML 文件圖片預設寬高比

Intrinsic aspect ratio of incomplete image

我在 2018 年有篇文章 Intrinsic Size 媒體寬高比,介紹一個標準的草案intrinsicsize,為什麼會需要這東西在那篇文章也有講,主要就是要搭配像是:

img {
  max-width: 100%;
  height: auto;
}

這種寫法非常通用,但是在圖片讀取完成前,<img />標籤的佔位會無法先知道,這會造成頁面在圖片讀取完成後瀏覽器會需要比較大的重新繪製的工作。

這幾天想起來去查了一下近況,發現竟然早早就停止發展了,caniuse 那邊 也顯示瀏覽器都把一些實驗中的支援都拿掉了,細看下去,發現 Firefox 的人當時說要開始試驗另一個比較優雅的方法,也有和 CSS WG 的人開始討論,他們當時的想法就是直接用widthheight屬性來計算寬高比(aspect ratio),不過之後就都沒有標準文件相關的發展細節或連結了。

搜尋一番後,發現 Firefox 在 71 開始就已經發佈這個修改了,當時的 release note 其實有寫,而且 MDN 上還有一篇文章:Mapping the width and height attributes of media container elements to their aspect-ratio,也有介紹這個修改要解決的問題以及技術上是怎樣處理的,簡單一點形容就是:

img { 
  aspect-ratio: attr(width) / attr(height); 
}

不過實際上不是真的使用這條 User Agent style 來實作就是了,因為這個透過widthheight計算出來的寬高比只有在圖片還沒讀取的時候會有效,圖片讀取完成後就會改成用圖片實際的尺寸來計算怎麼顯示了,所以要說它是預設的寬高比也不太正確。

在 CSS Image 這個 Module 的第四章:Sizing Images and Objects in CSS 中,有詳細的定義要怎樣決定圖片在繪製在網頁上時要怎樣處理,還定義了一些專有名詞:

  • Intrinsic dimensions 簡單一點形容就是圖片的原始尺寸,尺寸包含了寬(intrinsic width)、高和寬高比,不一定會全部都有,像是向量圖就只有寬高比,另外 intrinsic 中文翻譯是固有、或是根本的,所以 intrinsic dimentions 也不是真的就是圖片原始尺寸,它的文字敘述是:a preferred or natural size of the object itself。
  • Specified size 使用 CSS 設定的物件大小。
  • Concrete object size 根據上面兩個資訊所決定的實際上物件要繪製的大小,也就是我們眼睛所會看到的圖片呈現的大小。

所以主要就是在寫怎樣計算 concrete object size 了,大概計算過程就是和各位腦袋中想的不會差距太大。不過在這個地方,有一個細節是在 CSS 文件中故意沒有講出來的,就是怎樣取得 intrinsic dimensions,CSS 文件中沒有明確的說 intrinsic width 是來自圖片標籤的width屬性,或是圖片的實際寬度(早在 CSS 2.1 就有寫出 CSS 文件不定義怎樣取得該數值了)。其實 HTML 圖片的 intrinsic dimensions 要怎麼取得是放在 HTML 文件的 15.4.3,15 章都在講 rendering,15.4 則是 replaced elements,也就是圖片、影片之類的內容會整個替換掉的元素,15.4.3 最後一段的第一點是說圖片如果有抓下來的話就直接用圖片的 intrinsic aspect ratio,而第二點是這樣寫的:「If img'swidthandheightattribute values, when parsed using the rules for parsing dimension values), are both not an error, not a percentage, and non-zero, then use the ratio resulting from dividing thewidthattribute value by theheightattribute value.」這邊就明確的寫到用兩個屬性來計算 intrinsic aspect ratio 了,不過針對這個圖片讀取完成前的 intrinsic aspect ratio,並沒有定義一個專有名詞,所以可以看到 cnaiuse 用一個複雜的文字來敘述這項修改,要是我的話應該會把這個值命名為 intrinsic aspect ratio of incomplete image 之類的吧。

最後整理一下:

  • 圖片讀取完成前,如果有設定正確的數值的 width 和 hieght 的話,瀏覽器會先它們來計算 intrinsic aspect ratio
  • 圖片讀取完成後,瀏覽器會用圖片原始的寬高比來作為 intrinsic aspect ratio
  • 本來是希望能用在所有的 replaced elements,不過會造成既有網站壞掉所以目前限制在<img>標籤
  • 以上的修改是大約是今年前半年才進入瀏覽器的