網路上的可變字型簡介

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

本文將說明可變字型的定義、優點,以及如何運用在工作中。首先,請瞭解網頁上的排版運作方式,以及可變字型帶來的創新。

瀏覽器相容性

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

簡介

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

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

在可變字型推出前,每種樣式都是以獨立的字型檔案實作。有了可變字型,所有樣式都能包含在單一檔案中。

Roboto 系列不同樣式的樣本組成和清單。
左側:Roboto 字體系列的樣本。右側:系列中的具名樣式。

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

設計師建立印刷專案時,會遇到一些限制,例如頁面版面的實體大小、可使用的顏色數量 (取決於使用的印刷機類型) 等。但可以盡情使用字體樣式。也就是說,印刷媒體的字體通常豐富且精緻,可提供真正愉悅的閱讀體驗。回想上次瀏覽精美雜誌的體驗。

網頁設計師和開發人員與印刷設計師的限制不同,其中一項重要限制是設計的相關頻寬成本。這一直是更豐富的排版體驗的痛點,因為這些字體需要付費。使用傳統網頁字型時,設計中使用的每個樣式都需要使用者下載個別字型檔案,這會增加延遲和網頁算繪時間。光是包含 Regular 和 Bold 樣式,以及對應的斜體樣式,字型資料就可能達到 500 KB 以上。這甚至是在我們處理字型轉譯方式、需要使用的備用模式,或 FOIT 和 FOUT 等不良副作用之前。

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

變數字型剖析

可變字型將樣式封裝到單一檔案中,解決了這些問題。

這項功能會先從中央或「預設」樣式開始,通常是「一般」樣式,也就是最常見的粗細和寬度,最適合用於純文字的直立羅馬設計。然後,這個樣式會與連續範圍中的其他樣式連結,這個範圍稱為「軸」。最常見的軸是「粗細」,可將預設樣式連結至粗體樣式。任何個別樣式都可沿著軸線定位,並稱為可變字型的「執行個體」。部分例項是由字型開發人員命名,例如「粗細」軸位置 600 稱為「半粗體」。

可變字型 Roboto Flex 的「粗細」軸有三種樣式。「Regular」樣式位於中心,軸的兩端則分別是較輕和較重的樣式。在這些執行個體中,您可以選擇 900 個執行個體:

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

字型開發人員可以提供一組不同的軸。您可以合併這些樣式,因為它們都共用相同的預設樣式。Roboto 在寬度軸上有三種樣式:Regular 位於軸的中央,兩端則分別是較窄和較寬的樣式。這些值會提供 Regular 樣式的所有寬度,並與 Weight 軸結合,提供每個粗細的所有寬度。

Roboto Flex in random combinations of Width and Weight

這表示有數千種樣式!這或許看似過度,但這種多樣的字體樣式可大幅提升閱讀體驗品質。而且,如果不會影響效能,網頁開發人員可以視設計需求,使用任意數量的樣式。

斜體

可變字型處理斜體的方式很有趣,因為有兩種不同的做法。Helvetica 或 Roboto 等字體具有可插補的輪廓,因此其羅馬和斜體樣式可以在兩者之間插補,且 Slant 軸可用於從羅馬體轉換為斜體。

其他字體 (例如 Garamond、Baskerville 或 Bodoni) 的羅馬和斜體字元輪廓不相容於插補。舉例來說,一般定義羅馬小寫「n」的輪廓,與定義斜體小寫「n」的輪廓並不相符。斜體軸會從羅馬字體切換為斜體輪廓,而不是在兩者之間插補。

字體 Amstelvar 的粗細軸示例。
Amstelvar 的「n」輪廓 (斜體,12 點,一般粗細,一般寬度),圖片由字型設計師兼排版師 David Berlow 提供, 他是 Font Bureau 的成員。

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

您也可以查看個別字形的字形替代功能,並在可變字型的設計空間中隨處使用。舉例來說,以兩條垂直線設計的貨幣符號,最適合較大的點數大小,但如果點數較小,則以一條垂直線設計的貨幣符號較佳。如果用於算繪字形的像素較少,雙橫線設計可能會變得難以辨識。為解決這個問題,與斜體軸類似,字元可沿著 光學大小軸,在字體設計師決定的點進行字元替代。

總而言之,只要輪廓允許,字體設計師就能在多維設計空間中,建立可在各種樣式之間插補的字體。這樣一來,您就能精細地控管字體,並獲得極大的權力。

軸定義

有五個已註冊的軸,可控制字型的已知可預測功能:粗細、寬度、光學大小、傾斜和斜體。除了這些軸外,字型還可包含自訂軸。這些參數可控制字型設計師想要的字型設計,例如襯線大小、花體長度、升部高度或 i 上的點大小。

即使軸可以控制相同特徵,也可能使用不同的值。舉例來說,Oswald 和 Hepta Slab 可變字型只有一個軸 (粗細),但範圍不同。Oswald 的範圍與升級為可變字型前相同,都是 200 到 700,但 Hepta Slab 的範圍是 1 到 900,1 是極細的細線。

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

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

由於字型開發人員會定義可變字型中可用的軸,以及這些軸可用的值,因此瞭解每個字型提供的功能至關重要。字型的說明文件應會提供這項資訊,您也可以使用 Wakamai Fondue 等工具檢查字型。

用途和優點

設定軸值取決於個人喜好,以及是否採用排版最佳做法。任何新技術都有可能遭到濫用,而過於藝術或探索性的設定也可能降低實際文字的可讀性。對於標題而言,探索不同軸向來創造出色的藝術設計令人興奮,但對於內文而言,這可能會導致文字難以辨識。

令人興奮的表情

Mandy Michael 的草地範例
在 CodePen 中查看這個範例。

這個絕佳的藝術表現範例,探索了 Mandy Michael 的字體「Decovar」

動畫

Typeface Zycon 是由 Font Bureau 的字體設計師兼排版師 David Berlow 專為動畫設計的字體。

您也可以探索如何使用可變字型製作字元動畫。 上方的影片是使用 Zycon 字體時,不同軸的範例。請參閱 Axis Praxis 的動畫範例

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

以下是 Anicon 顏色圖示字型的幾個懸停動畫範例

Finesse

Amstelvar using little bits of XTRA in opposite directions so the words' widths are evened out

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 穩定設定的軸是 wght 軸 (透過 font-weight) 和 wdth 軸 (透過 font-stretch)。

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

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

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

同樣地,我們可以使用關鍵字 (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 的傾斜軸從最小值變更為最大值。

使用光學尺寸

字體可以很小 (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 提供幾種自訂軸,其中最重要的是「等級」(GRAD)。 等級軸很有趣,因為它會變更字型粗細,但不會變更寬度,因此換行符不會變更。使用「等級」軸時,您不必費心調整「粗細」軸的變更,以免影響整體寬度,也不必調整「寬度」軸的變更,以免影響整體粗細。

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 字型上的變數字型

Google 字型已擴充目錄,加入可變字型,並定期新增字型。目前介面旨在從字型中挑選單一例項: 選取所需變體,按一下「選取這個樣式」,系統就會將其新增至 <link> 元素,從 Google Fonts 擷取 CSS 和字型。

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

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

font-variation-settings 沿用

雖然現有 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>

瀏覽器會先套用 font-variation-settings: 'slnt' 10 類別的 .slanted。然後從 .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 字型,建議預先連線https://fonts.gstatic.com,也就是 Google 字型的代管網域。這樣一來,瀏覽器在 CSS 中遇到字型時,就能及早知道要從何處取得字型:

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

這項訣竅也適用於其他 CDN:越早讓瀏覽器設定網路連線,就能越早下載字型。

如要瞭解更多載入 Google 字型的效能提示,請參閱「The Fastest Google Fonts」。

備援和瀏覽器支援

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

/* 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,依此類推。

謝謝

本文的完成要感謝下列人士的協助: