CSS 中 font-size 定義的字體框(em box)大小,具體是怎麼實現的?

如題所示. 在《CSS 權威指南》中關於 "字體大小" 一節提到, 其實 font-size 定義的是 "字體框" 的大小. 而這個字體框是在設計字體本身時即定義了的.

但 "字體框" 大小並不總是剛好包含字元. 就是說在視覺上, 每個字元的真正大小實際是小於我們所看到的. 那麼, 這對於想精確控制行間距 (line-height) 就很困難.

我不懂字體設計, 因此希望這方面的專業同學幫我解答一下字體框和字元之間的空隙是怎麼計算的.


其實我覺得前端開發者不必在這方面想太多。

  • 對於 font-size,只要知道它取不同數值時(比如 font-size: 12)文本有多大就好。我們關心的是字對眼睛來說有多大、字的大小是否好讀,我們並不關心漢字「二」有多少個像素高、「一」有多少個像素高。

  • 對於 line-height,應當明白它是「行高」而非「行間距」,它是相鄰兩行文本相同部位的縱向距離(比如,上一行中字母 x 的左下角到下一行中字母 x 的左下角),並非兩行文本之間視覺空白的高度。應當了解不同行高時的大致效果(比如西文文本 line-height: 1.2 的效果,中文文本 line-height: 1.5 的效果……)。

* * * 以下很亂很無聊 * * *

如果真的想了解字體設計的細節,那麼我嘗試解釋一下(這些事情其實很簡單,但一旦說出來就很亂):

關於 em(還可參考維基百科: http://en.wikipedia.org/wiki/Em_(typography) ):

  • 字體是可以自由縮放的,所以字體設計時不用任何絕對單位(mm、pt、px 之類)。

  • 字體設計中,em 是個很基礎的概念(它和 HTML 的 & 標籤無關),一切長度都以它為參照。比如大寫字母通常大約是 700/1000 em 那麼高,而字母 x 通常大約是 450/1000 em 那麼高。

  • 以 1 em 為邊長畫一個正方形,這就是 em box。有時會把「em box」翻譯為「全形字框」(因為全形字元總是佔用 1 em 的橫向空間)。「字體框」這個譯法不合適,因為字體設計中有多種別的參考框架。對西文字體來說,em box 這個概念的意義不大,因為西文字元的寬度是自由的。
  • 不論在 Word 里、Photoshop 里還是 web 里,縮放字體時我們做的其實就是把 em 和某個絕對長度對應起來。當 em 與某個絕對長度有了對應,原本抽象的字體縮放到多大就確定了:如果我們設定字型大小(font size)為 12px,那麼字體的 1 em 就等於 12 px。這相當於我們在縮放字體設計的坐標系。
  • 西文字體和 em 的大小關係其實沒有標準。有的字體會相對大一些(比如 Verdana),有的字體會相對小一些(比如 Times New Roman),有的寬,有的窄。了解它們大致的大小就夠了。
  • 中文字體和 em 的關係比較明確。中文字體每個漢字佔用的橫向空間都是 1 em。比如,對於 12 px 的漢字文本,10 個字排在一起將佔用 120 px 的橫向空間。但由於漢字本身的面積其實不一樣(胖瘦不一樣),有的偏大(比如微軟雅黑),有的偏小(比如華文仿宋),所以儘管任何字體的 10 個漢字都會佔用 120 px 的橫向空間,這 10 個字的疏密情況不一樣。

關於問題補充說明(我感覺提問者其實是誤入了一條不符合主流習慣的歧途,然後想了太多,所以把問題想得比較糾結,所以我也只能儘力把補充說明裡的糾結思路費力地擰回來):

  • 「其實 font-size 定義的是『em box』的大小」——差不多是這樣。不過我建議理解為:設定字型大小時,我們設定了 em 的大小。
  • 「這個 em box 是在設計字體本身時即定義了的」——不對。Em 本身是天然存在的,字體設計是相對 em 來做的。字體設計時並沒有定義 em,字體設計是在 em 提供的坐標系裡繪圖,是相對 em 來決定圖形的大小。
  • 「『em box』大小並不總是剛好包含字元」——首先要區分字元(character)與字形(glyph),「字元」是存儲文字的單位,而「glyph」是我們看到的圖形。字體做的事就是告訴電腦要把一個字元顯示為什麼 glyph。Em box 永遠都不會剛好包含 glyph,因為 em 和 glyph 大小之間沒有預設的關係,它們的關係是字體設計的一部分。
  • 「就是說在視覺上,每個字元的真正大小實際是小於我們所看到的」——這句話說得很暈,其實我不太明白這是想表達什麼。我能說的就是:字形(glyph)的主體通常都不會超出 em box,西文字體的主體更是遠小於 em box。我們看到的是 glyph,而一個 glyph 有多大由兩方面因素決定:1. 字體設計師相對於 em 把這個 glyph 畫成了多大,2. 當前的字型大小(em 的大小)是多大。
  • 「這對於想精確控制行間距 (line-height) 就很困難」——前面說過,CSS 的 line-height 屬性控制的是行高,不是行間距。如果我們設定 line-height: 18px(或者設定 font-size: 12px; line-height: 1.5),那麼 10 行文本佔用的縱向空間就是 180 px。排版時,我們的習慣是設定行高為某值,然後觀察段落的疏密程度是否恰當。排版時說的「行間距」是這樣的:行間距 = 行高 - 字型大小。

    如果你真的想設定視覺上兩行文本之間有多少空白,鑒於這種排版思路不太主流,字體和排版工具都不提供介面,所以確實只能手動調校。我想強調一下:即使我們定義了「視覺行間空白」這樣一個概念(比如定義西文 x、a 等小寫字母上下都為「視覺行間」,漢字「圓」字上下都為「視覺行間」),對於不同字體和不同文字,相同的「視覺行間」大小也無法帶來相同的疏密效果,卻又讓排版變得複雜。

    所以請學會調整行高。行高是個很簡明的概念,不需要複雜的定義。而我們的目標是調整段落的疏密程度,所以直接觀察效果就好,不必關心行間的視覺空白高度的具體數值是多少。


推薦閱讀:

css sprite中的sprite應該如何翻譯比較達意?
css 關於同一個類里多個類名的優先順序?
拉勾網首頁——隨滑鼠滑動方向進緩慢插入圖片是怎麼實現的?
CSS 背景屬性不能繼承怎麼理解?
不用vh,vw,vmin,vmax,rem,em單位,不用js,如何獲得一個鎖定高寬比的響應式盒子?

TAG:前端開發 | 字體 | CSS |