Chromium 83 中 macOS system-ui 字型提供更多可變字型選項

Catalina 為 macOS 帶來全新的統一可變系統字型。

Dominik Röttsches
Dominik Röttsches

CSS 字型模組第 4 級規格中的「'system-ui'」部分定義了 system-ui 字型關鍵字,可讓開發人員在網站和應用程式中使用內建、經過超高速最佳化、經過本地化、超高品質且無需下載的預設作業系統字型。

body {
  font-family: system-ui;
}

這個字體設定的意思是「使用使用者目前所在地區的預設系統字型」。

在 macOS 上,system-ui 字型為 San Francisco,這是設計團隊審查、測試,並在最近升級的字型!首先,我們會介紹 Catalina 新增令人期待的變數字型功能,接下來介紹一些 錯誤,以及 Chromium 工程師的解決方法

本文假設您已熟悉可變字體。如果您不是影片,請觀看網路上的變數字型簡介,並觀看下方影片。

瀏覽器相容性

截至本文撰寫時,system-ui 已獲得 Chromium (自 56 版起)、Edge (自 79 版起)、Safari (自 11 版起) 和 Firefox (自 43 版起) 的支援,但使用 -apple-system 關鍵字。如需最新資訊,請參閱「我可以使用可變字型嗎?」。

新能力

自 Chromium 83 起,網頁開發人員可使用 Catalina 為系統字型帶來的新功能。system-ui 字型現在提供更多變數設定:光學大小和 2 種獨特的粗細調整:

Mojave
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}
Catalina
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

在 Mojave 中,system-ui 是僅有 wght 設定的可變字型。雖然 Catalina 上的 system-ui 是具有 wghtopszGRADYAXS 設定的變數字型。

我認為這裡有幾個不錯的漸進式改善設計機會!您可以深入探討系統字型的細微差異。

wght

可接受 0900 之間的字型粗細,並平均套用至所有字元。

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

光學調整大小功能與字間距或字母間距相似,但間距是由人眼而非數學計算所決定。19 以下的值適用於文字和內文文案間距,20 或以上值則適用於間距顯示標頭和標題。

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

與體重類似,但未觸及水平間距。可接受的值介於 4001000 之間。

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

將字符圖形垂直拉長。可接受的值介於 4001000 之間。

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

合併選項

只要幾行 CSS,我們就能調整字型設定,將字體調整為粗體,或嘗試其他有趣的組合:

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

就這樣,macOS 上的 Chromium 使用者會看到您升級的自訂 750 字重,以及其他有趣的調整 👍?

遊樂場

點選下方的「Glitch」即可供編輯的「Remix to Edit」,即可取得可編輯的 Glitch 副本,然後編輯新的 font-variation-settings 選項,看看會對字型造成什麼影響。請注意,只有在使用 macOS Catalina 裝置時,這個 Glitch 才能運作。

macOS 10.15 為系統字型新增了新功能,而 Chromium 錯誤追蹤器中記錄了 macOS 10.15 中的棘手 system-ui 錯誤。不知道它們有沒有關聯性!?

附錄:system-ui 迴歸

這個故事要從另一個錯誤開始說起:#1005969。這項問題是針對 macOS 10.15 回報的,因為 system-ui 字型間距看起來很窄,而且擠在一起。

比較 Facebook 群組頁面中的兩段文字。左側是 Chrome,右側是 Safari,Chrome 的間距較窄,但差異不大
左側為 Chrome (追蹤更密集),右側為 Safari (顯示間距更佳)

背景

你是否曾注意到,在 macOS 10.14 中,段落或標題的字型會在大小變動時「自動調整」為不同的字型?

在 Mojave (macOS 10.14) 上,system-ui 字型會依據目標字型大小,在兩種字型之間切換。當文字小於 20px 時,macOS 會使用「San Francisco Text」。當文字為 20px 以上時,macOS 會使用「San Francisco Display」。光學調整大小功能已靜態建構至兩個獨立的字型。

Catalina (macOS 10.15) 為舊金山推出新的統一變數字型。您不再需要管理「文字」和「顯示」。也獲得先前所述的新變化版本設定 opsz

h1 {
  font-variation-settings: 'opsz' 20;
}

很抱歉,新版 Catalina 字型的預設 opsz 值為 20,而 Chromium 工程師尚未準備將 opsz 套用至系統字型。這會導致較小的尺寸顯示過窄。

為修正這個問題,Chromium 需要將 opsz 正確套用至系統字型。這項修正已解決 問題 #1005969。獲勝了!還是...?

尚未完成

這就是棘手之處:Chromium 套用了 opsz,但某些內容仍顯示不正確。Mac 上的系統字型有額外的字型表格,稱為 trak,可調整水平間距。解決問題時,Chromium 工程師發現在 macOS 中,從 CTFontRef 物件擷取水平指標時,trak 指標已經納入指標結果中。Chromium 的塑形程式庫 HarfBuzz 需要尚未納入 trak 值的指標。

系統 UI 和清單中所有字型粗細和變化版本的顯示畫面。其中有一半沒有套用權重差異。
左:套用粗體的字型大小為 19 以下。右側:字型大小 20 以上會失去粗體樣式

在內部,Skia (圖形程式庫,而非同名字型) 會同時使用 CoreGraphicsCGFontRef 類別,以及 CoreTextCTFontRef 類別。由於這些物件之間需要進行內部轉換 (用於維持向後相容性,以及在兩個類別中存取所需的 API),因此 Skia 會在特定情況下遺失粗體資訊,而粗體字型也會停止運作。我們已在問題 #1057654 中追蹤這個問題。

Skia 仍需支援 macOS 10.11,因為 Chromium 仍支援該版本。在 10.11 版中,「San Francisco Text」和「San Francisco Display」字型甚至不是可變字型。而是每個粗細都會是獨立的字型系列。他們的字符 ID 有時無法同步。因此,如果 Skia 使用「San Francisco Display」繪製文字形狀 (將文字轉換為可繪製的字符),使用「San Francisco Display」繪製文字時就會呈現胡言亂語,反之亦然。即使 Skia 要求的尺寸不同,macOS 也可能會切換到其他尺寸。您應該可以一律使用其中一個字型,然後縮放 (使用矩陣縮放,而非要求更大的大小),但 CoreText 有個問題,它不會縮放 sbix (彩色表情符號) 字形 (只會縮小)。實際上,情況稍微複雜一點。實際上,CoreText 似乎是在矩陣應用程式之後的垂直範圍上限,這似乎與這個應用程式無法以 45 度角繪製表情符號。無論如何,如果要顯示大型表情符號,就必須複製字型,才能取得大型版本。

因此,為了在內部建立不同大小的 CTFont 物件副本,同時確保使用相同的基礎字型資料,Chromium 會從 CTFont 中拉出 CGFont,然後從 CGFont 建立新的 CTFont (CGFont 物件不受大小影響,魔法切換會在 CoreText 層級發生)。這個方法在 10.154 之前運作正常。在 10.15 版中,這個 round trip 最終會遺失太多資訊,導致重量問題。Flutter 發現權重問題,並針對大小調整替代修正方式,是直接從原始 CTFont 建立新的 CTFont,同時利用 CoreText 中未記錄的舊屬性來直接控制光學大小。這樣可讓產品在 10.11 版中持續運作並修正其他問題,例如明確將光學大小設為預設值。

不過,這會在字型中保留更多的 CoreText「魔術指令」。其中一個原因似乎是,它仍會以某種方式調整圖示進度,而非只使用 trak 表格 (Chromium 已嘗試透過另一個未記錄的屬性抑制應用程式)。

CGFont 不會執行任何「魔法」,因此 Chromium 可以從 CTFont 取得 CGFont,然後用來取得進階功能嗎?很抱歉,這麼做不會成功,因為 CoreText 也會以其他方式影響字型。舉例來說,它會讓小表情符號比實際要求的稍大 (稍微放大)。CGFont 不知道這一點,因此您最終會發現以 sbix 為基礎的表情符號彼此間距過於接近,因為您會以某個大小進行測量,但 CoreText 會將其繪製得更大一些。Chromium 確實希望採用 CTFont 的進階功能,但希望在沒有追蹤的情況下執行,且最好不要有任何其他雜訊。

由於要修正間距問題,系統需要互連的 Blink 與 Skia 修復作業,因此 Chromium 工程師無法「只還原」來解決問題。Chromium 工程師也嘗試使用不同的建構標記來變更 Skia 中的字型相關程式碼路徑,這雖然解決了粗體字型問題,但卻導致間距問題復發。

修正方法

最後,Chromium 想修正這兩個問題。Chromium 現已改用 HarfBuzz 內建的字型 OpenType 字型基準功能,直接從系統字型的字型表中擷取水平基準。使用這個方法,Chromium 會在字型有 trak 表格時避開 CoreText 和 Skia (除非是表情符號字型)。

系統 UI 和清單中所有字型粗細和變化版本的顯示畫面。原本無法執行的一半現在看起來很不錯。

同時,仍有 Skia 問題 #10123 可以在 Skia 中完整追蹤這個問題,並返回使用 Skia 從該位置擷取系統字型指標,而非使用 HarfBuzz 的最新修正內容。