color function is not supported

最近有一個需求要將當前畫面儲存成圖片下載。於是我找到 html2canvas 這個將畫面 html 內容繪製成 canvas 內容的套件。

整合過程很順利,我一路過關斬將從 Firefox, Chrome,然後到 iPhone 裡頭的 Safari。但就在我從手機裡頭儲存圖片卻失靈了。礙於 iPhone 裡頭 Safari 不容易除錯,我改從 Macos 的 Safari 測試。結果一樣發生錯誤。並且 Console 顯示了下列錯誤:

Unhandled Promise Rejection:
Error:
Attempting to parse an unsupported color function "color"

透過追蹤代碼,我知道 html2canvas 會在渲染的時候檢查相關的 css 屬性。其中 color function 無法被正確渲染。所以回頭檢查 html 代碼,確定沒有使用 color 的部分。但為何錯誤會發生在我的某個 html 元素有使用 color?

:disabled Pseudo-Class

為了盡快釐清問題,我開始將部分的 html 移除,試著縮小範圍。而當我將畫面上的表單內容移除之後,功能居然正常了!為何?

更進一步,我將表單留到只剩下一個 input 元素

<input name="phone" type="text" inputmode="numeric"
  pattern="\d{11}"
  oninput="this.value=this.value.replace(/[^0-9]/g,'')" disabled=""
  placeholder="請輸入手機"
  minlength="11"
  maxlength="11" />

由於這個元素有多個屬性使用,我逐步地刪除,直到發現把 disabled="" 移除之後功能正常了。但是,這又是為何?

由於為了避免 CSS 預設瀏覽器差異,我在最上頭使用 reset.css 重新設定 css 樣式。按理瀏覽器彼此的差異應該所剩無幾,很快地想到預設的 :disabled 可能使用了 color function 定義顏色。於是我找到 What color do disabled text-boxes in html uses? 確認了我的疑慮。

然後透過瀏覽器確認預設 input:disabled 樣式是:

input:disabled, textarea:disabled {
  color: color(srgb 0.34 0.34 0.34);
}

於是我自定義了一組 css 樣式覆蓋原本的樣式:

input:disabled {
  color: #C6C6C6;
}

重新執行一次之後 Safari 正常了。接著在手機上的 Safari 也順利成功。

看不見的細節

這個問題,一開始認為是套件的問題。可能對 Safari 的支持不佳,於是開啟官方網站,用官網的 capture 功能擷取畫面,結果沒問題。

轉而檢查自己的 html 內容。在找不到線索的時候,才透過刪去法限縮範圍,想不到最後會在一個 disabled 屬性上發現問題。

若不是該 input 元素預設即為 disabled,如果是在動態切換的過程設定 disabled。恐怕這次除錯會難上加難了🥲。