網路上的可變字型簡介

新的字型規格,可大幅縮減字型檔案大小

本文將說明變數字型為何,以及其帶來的優點,並說明如何在工作中使用變數字型。首先,我們來複習一下字體排版在網路上的運作方式,以及可變字體帶來的創新。

瀏覽器相容性

截至 2020 年 5 月,大多數瀏覽器都支援可變字型。請參閱「可否使用可變字型?」和「備用字型」。

簡介

開發人員經常混用「字型」和「字體」這兩個詞彙。不過,兩者還是有差異:字體是基礎視覺設計,可用於許多不同的排版技術;字型則是其中一種實作方式,以數位檔案格式呈現。換句話說,字體樣式是您「看到」的內容,而字型是您「使用」的內容。

另一個經常被忽略的概念是樣式和系列之間的差異。樣式是單一特定字體,例如粗斜體,而系列則是完整的樣式組合。

在可變字型推出之前,每種樣式都會實作為獨立的字型檔案。使用可變字型時,所有樣式都可以包含在單一檔案中。

Roboto 系列的示例組合和不同樣式的清單
左:Roboto 字體系列的範例。右側:系列中的命名樣式。

設計人員和開發人員面臨的挑戰

設計師在建立沖印專案時,會面臨一些限制,例如頁面版面配置的實際大小、可使用的顏色數量 (取決於要使用的印刷機類型) 等等。但他們可以使用任意數量的字體樣式。也就是說,平面媒體的排版通常都很豐富且精緻,因此閱讀體驗非常愉悅。回想上次瀏覽精彩雜誌的情況。

網頁設計師和開發人員的限制條件與平面設計師不同,其中一個重要的限制條件是設計相關的頻寬成本。這一直是更豐富的排版體驗的難題,因為這類體驗的成本較高。使用傳統的網路字型時,設計中使用的每種樣式都需要使用者下載個別的字型檔案,這會增加延遲時間和頁面算繪時間。僅包含 Regular 和 Bold 樣式,以及其斜體對應項目,字型資料大小可能就會達到 500 KB 以上。即使我們尚未處理字型算繪方式、需要使用的備用模式,或不必要的副作用 (例如 FOIT 和 FOUT),也要先處理這個問題。

許多字型系列提供更廣泛的樣式,從 Thin 到 Black 的粗細、窄和寬的寬度、各種樣式細節,甚至是特定尺寸的設計 (針對大或小文字大小進行最佳化)。由於您必須為每種樣式 (或樣式組合) 載入新的字型檔案,許多網頁開發人員都選擇不使用這些功能,以免降低使用者的閱讀體驗。

變數字型的解剖

變數字型會將樣式打包成單一檔案,以解決這些問題。

這項功能會從中央或「預設」樣式開始,通常是「Regular」(一般),這是直立的羅馬設計,具有最典型的粗細和寬度,最適合用於純文字。接著,這會連結至連續範圍內的其他樣式,稱為「軸」。最常見的軸是「粗細」,可將預設樣式連結至粗體樣式。任何個別樣式都可以沿著軸線定位,並稱為變數字型的「例項」。有些字型例項是由字型開發人員命名,例如重量軸位置 600 稱為 SemiBold。

變數字型 Roboto Flex粗細軸有三種樣式。一般樣式位於中間,軸線兩端有兩種樣式,一種較輕,另一種較重。您可以選擇下列 900 個執行個體:

以不同粗細顯示的字母「A」
上圖:Roboto 字體的粗細軸解剖圖。

字型開發人員可以提供一組不同的軸。您可以將這些樣式合併,因為它們都使用相同的預設樣式。Roboto 的寬度軸有三種樣式:Regular 位於軸的中央,兩個樣式 (較窄和較寬) 則位於兩端。這些屬性會提供 Regular 樣式的所有寬度,並與 Weight 軸結合,提供所有重量的寬度。

Roboto Flex 的寬度和粗細隨機組合

也就是說,有數千種樣式!這可能看起來過於誇張,但這種多樣化的字型樣式,可以大幅提升閱讀體驗品質。如果沒有效能懲罰,網頁開發人員可以使用少量或大量的樣式,這取決於他們的設計。

斜體

在可變字型中處理斜體的方式很有趣,因為有兩種不同的做法。Helvetica 或 Roboto 等字型具有可與插補相容的輪廓,因此可以將其羅馬式和斜體樣式插補,並使用「Slant」軸將羅馬式轉換為斜體。

其他字型 (例如 Garamond、Baskerville 或 Bodoni) 的羅馬和斜體字元輪廓不支援插補。舉例來說,通常定義羅馬小寫字母「n」的輪廓,與用於定義義大利文小寫字母「n」的輪廓不符。Italic 軸並不會將一個輪廓外推至另一個輪廓,而是切換從羅馬式字型切換至斜體字型。

Amstelvar 字體的粗細軸範例
Amstelvar 的「n」輪廓,以斜體 (12 點、一般粗細、一般寬度) 和羅馬體顯示。圖片由 Font Bureau 的字型設計師兼排版師 David Berlow 提供。

切換為斜體後,使用者可用的軸應與羅馬字母相同,字元集也應相同。

字符替換功能也適用於個別字符,並可用於可變字型的設計空間中的任何位置。舉例來說,含有兩個垂直條的美元符號設計最適合較大的點陣圖,但在較小的點陣圖中,含有一個條的設計會比較適合。如果我們用於轉譯符號的像素較少,兩條線條的設計可能會變得難以辨識。為解決這個問題,類似斜體軸,在字型設計者決定的點上,沿著Optical Size軸,可發生一個字形替換為另一個字形的情況。

總而言之,在輪廓允許的情況下,字型設計人員可以建立字型,在多維設計空間中插補各種樣式。這樣一來,您就能精細控管您的字體排版,並發揮極大效用。

軸定義

有五個註冊軸可控制字型的已知、可預測的功能:粗細、寬度、光學大小、傾斜和斜體。除了這些之外,字型也可以包含自訂軸。這些屬性可控制字型設計師想要的任何設計面向,包括襯線字型大小、斜線長度、升線高度或 i 上的圓點大小。

雖然軸可以控制相同的特徵,但可能會使用不同的值。舉例來說,在 Oswald 和 Hepta Slab 可變字型中,只有一個可用的軸,即粗細,但範圍不同:Oswald 的範圍與升級為可變字型前的範圍相同,即 200 到 700,但 Hepta Slab 的極細粗細為 1,可達到 900。

五個已註冊的軸都有 4 個小寫字元的標記,用於在 CSS 中設定其值:

軸名稱和 CSS 值
重量 wght
寬度 wdth
slnt
光學尺寸 opsz
斜體 ital

由於字型開發人員會定義可在可變字型中使用的軸線,以及這些軸線可使用的值,因此必須找出每個字型提供的內容。字型說明文件應會提供這項資訊,您也可以使用 Wakamai Fondue 等工具檢查字型。

用途和優勢

設定軸值時,請根據個人喜好和字體排版最佳做法。任何新技術都可能遭到濫用,而過度藝術化或探索性的設定,也可能會降低實際文字的可讀性。在標題部分,探索不同軸線以創造出精彩的藝術設計很有趣,但如果是內文,則可能會導致文字難以辨識。

令人興奮的表情

曼蒂·麥可 (Mandy Michael) 的草地範例

上方顯示的藝術創作是 Mandy Michael 探索字型 Decovar 的絕佳例子。

如要查看上述範例的有效範例和原始碼,請按這裡

動畫

字型 Zycon 是 Font Bureau 的字型設計師兼排版師 David Berlow 為動畫設計的字型。

您也可以嘗試使用可變字型為字元製作動畫。上方範例顯示了使用 Zycon 字體時的不同軸線。請參閱 Axis Praxis 上的動畫範例

Anicons 是全球第一個以 Material Design 圖示為基礎的動畫彩色圖示字型。Anicons 是一種實驗,結合了兩種尖端字型技術:可變字型和彩色字型。

幾個 Anicon 彩色圖示字型懸停動畫範例

Finesse

Amstelvar 會在相反方向使用少量 XTRA,讓字詞的寬度平均分配

Roboto FlexAmstelvar 提供一組「參數軸」。在這些軸線上,字母會被分解為 4 個基本形式:黑色或正形狀、白色或負形狀,以及 x 和 y 維度。就像原色可以與任何其他顏色混合以進行調整一樣,這 4 個面向可用於微調任何其他軸線。

Amstelvar 中的 XTRA 軸可讓您調整每百萬個單位的「白色」值,如上圖所示。使用 XTRA 的少量字元,在相反方向上,字詞的寬度會平均分配。

CSS 中的變數字型

載入變數字型檔案

變數字型會透過與傳統靜態網頁字型相同的 @font-face 機制載入,但有兩項新的增強功能:

@font-face {
    font-family: 'Roboto Flex';
    src: url('RobotoFlex-VF.woff2') format('woff2-variations');
    src: url('RobotoFlex-VF.woff2') format('woff2') tech('variations');
    font-weight: 100 1000;
    font-stretch: 25% 151%;
}

1. 來源格式:如果瀏覽器不支援可變字型,我們不希望瀏覽器下載字型,因此我們新增 formattech 說明:一次在未來語法 (format('woff2') tech('variations')) 中,一次在已淘汰但在瀏覽器中支援的語法 (format('woff2-variations')) 中。如果瀏覽器支援可變字型且支援即將推出的語法,則會使用第一個宣告。如果支援變數字型和目前的語法,就會使用第二個宣告。兩者都指向相同的字型檔案。

2. 樣式範圍:您會發現我們為 font-weightfont-stretch 提供兩個值。我們現在會提供字型支援的粗細範圍,而非告知瀏覽器這個字型提供的特定粗細 (例如 font-weight: 500;)。對於 Roboto Flex,重量軸的範圍為 100 到 1000,CSS 會直接將軸範圍對應至 font-weight 樣式屬性。在 @font-face 中指定範圍後,系統會將超出範圍的任何值「上限」為最接近的有效值。寬度軸範圍會以相同方式對應至 font-stretch 屬性。

如果您使用 Google Fonts API,系統會自動處理這項作業。CSS 不僅會包含適當的來源格式和範圍,如果系統不支援可變字型,Google 字型也會傳送靜態備用字型。

使用權重和寬度

目前,您可以透過 CSS 可靠地設定的軸線是透過 font-weightwght 軸,以及透過 font-stretchwdth 軸。

傳統上,您會將 font-weight 設為關鍵字 (lightbold),或設為介於 100 和 900 之間的數值,步進為 100。使用可變字型時,您可以設定字型寬度範圍內的任何值:

.kinda-light {
  font-weight: 125;
}

.super-heavy {
  font-weight: 1000;
}
Roboto Flex 的 Weight 軸從最小值變更為最大值。

同樣地,我們可以使用關鍵字 (condensedultra-expanded) 或百分比值設定 font-stretch

.kinda-narrow {
  font-stretch: 33.3%;
}

.super-wide {
  font-stretch: 151%;
}
將 Roboto Flex 的寬度軸從最小值變更為最大值。

使用斜體和斜體

ital 軸適用於同時包含一般樣式和斜體樣式的字型。軸是開/關切換鈕:值 0 為關閉,會顯示一般樣式,值 1 會顯示斜體。與其他軸不同,這裡沒有轉場效果。0.5 的值不會產生「半斜體」。

slnt 軸與斜體不同,它不是新的樣式,而是將一般樣式傾斜。預設值為 0,代表預設的直立字母形狀。Roboto Flex 的最大傾斜角度為 -10 度,也就是說,字母會從 0 傾斜至 -10。

透過 font-style 屬性設定這些軸會很直覺,但截至 2020 年 4 月,具體做法仍在研擬中。因此,您目前應將這些軸視為自訂軸,並透過 font-variation-settings 設定:

i, em, .italic {
    /* Should be font-style: italic; */
    font-variation-settings: 'ital' 1;
}

.slanted {
    /* Should be font-style: oblique 10deg; */
    font-variation-settings: 'slnt' 10;
}
Roboto Flex 的 Slant 軸從最小值變更為最大值。

使用光學尺寸

字型樣式可以顯示為非常小 (12 像素的註腳) 或非常大 (80 像素的標題)。字型可以回應這些大小變化,藉由變更字母形狀來配合大小。小尺寸的圖片不太適合顯示精細的細節,而大尺寸的圖片則可顯示更多細節和較細的筆觸。

以不同光學尺寸顯示的字母「a」
Roboto Flex 字母「a」的不同像素大小,經過縮放後會顯示出設計上的差異。您也可以在 Codepen 上親自試試

我們為這個軸新增了 CSS 屬性:font-optical-sizing。預設值為 auto,可讓瀏覽器根據 font-size 設定軸值。這表示瀏覽器會自動挑選最佳的光學大小,但如果您想關閉這項功能,可以將 font-optical-sizing 設為 none

如果您刻意想要讓光學大小不符合字型大小,也可以為 opsz 軸設定自訂值。下列 CSS 會導致文字以大尺寸顯示,但以視覺尺寸顯示,就像是使用 8pt 列印一樣:

.small-yet-large {
  font-size: 100px;
  font-variation-settings: 'opsz' 8;
}

使用自訂軸

與註冊軸不同,自訂軸不會對應至現有的 CSS 屬性,因此您必須一律透過 font-variation-settings 設定這些軸。自訂軸的標記一律為大寫,以便與已註冊的軸做出區別。

Roboto Flex 提供幾個自訂軸,其中最重要的是 Grade (GRAD)。Grade 軸很有趣,因為它可以變更字型的粗細,而不變更寬度,因此換行符號不會變更。透過調整等級軸,您可以避免被迫調整會影響整體寬度的重量軸,然後再調整會影響整體重量的寬度軸。

Roboto Flex 的 Grade 軸從最小值變更為最大值。

GRAD 是自訂軸,在 Roboto Flex 中的範圍為 -200 到 150。我們需要使用 font-variation-settings 解決這個問題:

.grade-light {
    font-variation-settings: `GRAD` -200;
}

.grade-normal {
    font-variation-settings: `GRAD` 0;
}

.grade-heavy {
    font-variation-settings: `GRAD` 150;
}

Google Fonts 上的變數字型

Google Fonts 已擴充目錄,加入可變字型,並定期新增字型。這個介面目前旨在從字型中挑選單一例項:您選取所需變化版本,然後點選「選取此樣式」,系統就會將該變化版本加入 <link> 元素,以便從 Google 字體擷取 CSS 和字型。

如要使用所有可用的軸或值範圍,您必須手動撰寫 Google Fonts API 的網址。可變字體總覽會列出所有軸和值。

Google 變數字型連結工具也可以提供完整變數字型的最新網址。

字型變化設定繼承

雖然所有已註冊的軸很快就會透過現有的 CSS 屬性獲得支援,但目前您可能需要使用 font-variation-settings 做為備用方案。如果您的字型有自訂軸,也需要 font-variation-settings

不過,font-variation-settings 有一個小問題。系統會自動將您未明確設定的每個屬性重設為預設值。先前設定的值不會繼承!也就是說,以下項目無法正常運作:

<span class="slanted grade-light">
    I should be slanted and have a light grade
</span>

瀏覽器會先套用 .slanted 類別的 font-variation-settings: 'slnt' 10。然後會套用 .grade-light 類別中的 font-variation-settings: 'GRAD' -200。但這麼做會將 slnt 重設為預設的 0!結果會是淺色等級的文字,但不會傾斜。

幸好,我們可以使用 CSS 變數來解決這個問題:

/* Set the default values */
:root {
    --slnt: 0;
    --GRAD: 0;
}

/* Change value for these elements and their children */
.slanted {
    --slnt: 10;
}

.grade-light {
    --grad: -200;
}

.grade-normal {
    --grad: 0;
}

.grade-heavy {
    --grad: 150;
}

/* Apply whatever value is kept in the CSS variables */
.slanted,
.grade-light,
.grade-normal,
.grade-heavy {
    font-variation-settings: 'slnt' var(--slnt), 'GRAD' var(--GRAD);
}

CSS 變數會層層遞迴,因此如果元素 (或其中一個父項) 將 slnt 設為 10,即使您將 GRAD 設為其他值,它仍會保留該值。如需這項技巧的詳細說明,請參閱「修正可變字型繼承」。

請注意,CSS 變數的動畫效果無法運作 (這是設計上的考量),因此下列效果無法運作:

@keyframes width-animation {
   from { --wdth: 25; }
   to   { --wdth: 151; }
}

這些動畫必須直接在 font-variation-settings 上執行。

提高廣告成效

OpenType 可變字型可讓我們將字型系列的多種變化版本儲存至單一字型檔案中。Monotype 進行了一項實驗,將 12 個輸入字型組合起來,產生八種粗細,並在斜體和羅馬風格中各自使用三種寬度。在單一可變字型檔案中儲存 48 個個別字型,可減少 88% 的檔案大小

不過,如果您只使用 Roboto Regular 等單一字型,且沒有其他字型,切換為具有多個軸線的可變字型,可能不會看到字型大小的淨增幅。一如既往,這取決於您的用途。

另一方面,在設定之間為字型製作動畫可能會導致效能問題。雖然瀏覽器支援可變字型後,這個問題會有所改善,但如果只為目前在螢幕上顯示的字型製作動畫,就能進一步減少這個問題。這個由 Dinamo 提供的實用程式碼片段,可在元素不在畫面上時暫停使用 vf-animation 類別的動畫:

var observer = new IntersectionObserver(function(entries, observer) {
  entries.forEach(function(entry) {
    // Pause/Play the animation
    if (entry.isIntersecting) entry.target.style.animationPlayState = "running"
    else entry.target.style.animationPlayState = "paused"
  });
});

var variableTexts = document.querySelectorAll(".vf-animation");
variableTexts.forEach(function(el) { observer.observe(el); });

如果您的字型會回應使用者互動,建議您節制或去抖動輸入事件。這可防止瀏覽器轉譯可變字型的例項,因為這些例項與先前的例項差異不大,人眼無法察覺差異。

如果您使用 Google Fonts,建議您預先連線https://fonts.gstatic.com,也就是 Google 字型代管的網域。這樣一來,瀏覽器在 CSS 中遇到字型時,就能提早知道從何處取得字型:

<link rel="preconnect" href="https://fonts.gstatic.com" />

這項提示也適用於其他 CDN:讓瀏覽器盡快設定網路連線,就能盡快下載字型。

如要進一步瞭解載入 Google 字型的最佳做法,請參閱「最快的 Google 字型」。

備用方案和瀏覽器支援

所有新型瀏覽器都支援可變字體。如果您需要支援舊版瀏覽器,可以選擇使用靜態字型建構網站,並使用可變字型做為漸進式增強功能:

/* Set up Roboto for old browsers, only regular + bold */
@supports not (font-variation-settings: normal) {
  @font-face {
    font-family: Roboto;
    src: url('Roboto-Regular.woff2');
    font-weight: normal;
  }

  @font-face {
    font-family: Roboto;
    src: url('Roboto-Bold.woff2');
    font-weight: bold;
  }

  body {
    font-family: Roboto;
  }

  .super-bold {
    font-weight: bold;
  }
}

/* Set up Roboto for modern browsers, all weights */
@supports (font-variation-settings: normal) {
  @font-face {
    font-family: 'Roboto';
    src: url('RobotoFlex-VF.woff2') format('woff2 supports variations'),
         url('RobotoFlex-VF.woff2') format('woff2-variations');
    font-weight: 100 1000;
    font-stretch: 25% 151%;
  }

  .super-bold {
    font-weight: 1000;
  }
}

對於舊版瀏覽器,具有 .super-bold 類別的文字會以一般粗體顯示,因為這是我們唯一可用的粗體字型。在支援可變字型時,我們可以實際使用 1000 這個最重的粗細。

Internet Explorer 不支援 @supports 規則,因此這個瀏覽器不會顯示任何樣式。如果這是問題所在,您可以隨時使用其中一個老式駭客攻擊來指定相關的舊版瀏覽器。

如果您使用 Google Fonts API,系統會為訪客的瀏覽器載入適當的字型。假設您要求 Oswald 字型的粗細範圍為 200 到 700,如下所示:

<link href="https://fonts.googleapis.com/css2?family=Oswald:wght@200..700&display=swap" rel="stylesheet">

可處理可變字型的新式瀏覽器會取得可變字型,並提供 200 到 700 之間的所有粗細。較舊的瀏覽器會收到每個粗細的個別靜態字型。在這種情況下,這表示他們會下載 6 個字型檔案:一個是粗細 200,另一個是粗細 300,依此類推。

謝謝

以下人員協助完成本文:

主頁橫幅圖片由 Bruno Martins 提供,取自 Unsplash