@ChingHanHo

I Build Stuff.

CSS Font (1) - 基本概念

2048

(圖片取自「Digitizing Letterform Designs」,版權為原網站所有。)

瞭解電腦字型如何被創造,能夠進一步理解文字如何在螢幕上顯示。本系列文章目的在於研究電腦字型在螢幕上顯示的原理,以便理解 CSS 有關字型的各項屬性背後的設計目的,以及要解決的問題。本文適合對象為從事網頁設計的專業人員,不論是網頁設計師、前端工程師,或是全端工程師。

EM square

傳統金屬活版印刷把每個字母刻在一個金屬方塊上,方塊不一定是正方形,寬度可能不同但是高度相同,這樣才能整齊地排列字母。由於英文中「M」這個字母比例接近正方形幾乎是最大的一個,因此金屬塊的寬度被稱為「em(M)」。

在數位時代一個字母的空間容器從實體金屬塊轉移到虛擬的電腦程式上,電腦程式會建構一個虛構的空間容器被稱為 EM square、EM size 或 UPM(Unit per EM),術語源自活版印刷技術的歷史,而數位字型也將以此作為容器基礎。

字體(typeface)指的是文字的外觀風格,常見的字體例如標楷體、新細明體、微軟正黑體、蘋方體、Times New Roman、Helvetica 等,基於相似概念組成的集合便稱為字體家族(font family),也是 CSS 的 font-family 所設定的名稱。

字形(glyph)指的是字元的形狀,由程式演算法或是文字工程師、設計師手動調整的形狀本身。一個字型的所有字形都有相同的 EM square 尺寸,差別在於字形的大小不同。

EM square

在技術上 EM square 可以看作是個有限的二維空間座標系統(x,y),寬高可能是 2048x2048(單位 FUnit),OpenType 官方規格建議大小是 16 到 16384 之間,但如果主流軟體無法支援便失去了意義,例如 InDesign、Illustrator 特定版本無法正確處理 EM square 超過 5000 的字型,所以 EM square 的尺寸需要取決於軟體的相容性。目前比較常見的尺寸通常是 1000 或是 2048,例如 Apple 主要字型都是以 2048 FUnit 去設計的。

字形基本上都會設計在 EM square 的範圍內,但也能超出這個範圍,視字型製造商的偏好及決定。

Character extending outside of the em square.

當指定 CSS font-size 16px 瀏覽器便會將字型 EM square 的大小映射到螢幕 16px 的大小上,可以參考我的另一篇文章「CSS Font (2) - 像素」。

字形解構

觀察英文字母的書法規則,可以歸納出一些模式,例如每個字母基本上都坐落在同一條水平線上,這條水平線稱為基準線(baseline),相對於其他字型或字形決定如何對齊,不過這是針對英文(正確來說是拉丁文)字型設計,中文字型由於都是方形等寬等高的,因此不需要基準線的設計。

此外,基線到字形最高的頂部稱為升部(Ascent);基線到字形最底的底部稱為降部(Descent)。在數位字型中,這項規格制定在 OpenType、TrueType 的 OS/2 表格sTypoAscendersTypoDescender 的值,或是 HHEA 表格中的 AscentDescent。OS/2 是給 Windows 的規格、HHEA 則是 Apple 的規格。

行高

印刷排版中的行高英文是 leading,指的是兩行文字中間的距離或空白,但是 CSS 的行高(line height)略有不同的定義,因為它不是只是單純地加在行與行的中間,而是先計算出 leading:

leading = line-height - (ascent + descent)

然後 CSS 將其中一半的 leading 加到文字的上方,一半加到下方。舉例來說,指定某區塊字級大小 16px,行高設定 24px,則 (24 - 16) = 4,CSS 會在 16px 的文字上面及下面同時加上 4px 的空白,最後整體文字區塊(inline box)才會得到 24px 的高度。

W3 規定 CSS line-height 預設的值是 normal,並且建議這個值可以介於 1.0 ~ 1.2 之間。為了測試實際 line-height 到底是多少,我準備了一個測試網頁,在 Chrome 跟 Firefox 兩種不同的 render engine 測試不同英文字跟中文字體,得到以下 4 個測試結果:

  • 不同瀏覽器 normal 不同;
  • 同個瀏覽器 font-size 不同 normal 實際值也不同;
  • 同個瀏覽器 font-size 相同 font-family 不同 normal 實際值也不同;
  • 雖然 W3 建議 normal 應該介於 1.0 ~ 1.2 但實際上隨著 font-sizefont-family 變化,可能會大於 1.2;

line-height-compare

不同瀏覽器預設 line-height 不同,要解決這個問題也容易,只要在 <html><body> 指定固定的值即可,例如 normalize.css 指定了 line-height 為 1.15,reset.css 設定 line-height 為 1。

Comments