深度剖析Baseline設計原理

美團點評點餐發表於2017-09-26

前言:Baseline是很多前端人都用過的最基本的CSS屬性之一,乍一看來,似乎很簡單,但真的深究起來,Baseline可以算得上CSS最有深度的屬性之一了。不信,那就繼續往下看。

目錄

  • 字型大小

    • 字型大小相同,高度不同
    • 字型是如何製造出來的
  • Baseline的位置

    • 不同display值的Baseline的位置
    • 從vertical-align的值來了解Baseline的兄弟屬性的值的含義。

一、字型大小

(1)字型大小相同,高度不同

先來看一個簡單的例子:

<p>
    <span style="font-family:Catamaran;font-size:100px;">MO</span>
    //Catamaran就是Google字型庫中的原生
    <br>
    <span style="font-family:Catamaran-special;font-size:100px;">MO</span>
    //Catamaran是在原生的基礎上做了尺寸改動(只改動了佈局,沒改動字型設計風格,你就權當是一種新的字型),文章會有說明。
</p>複製程式碼

這一段程式碼中兩個span唯一的不同就是font-family不同,來看一下他們表現的結果:

深度剖析Baseline設計原理

此處,選中文字,你會發現設定了同樣大小的font-size為什麼會出現高度不同這樣的差異呢?

接下來就要去了解vertical-align中的各個引數的值了:(top,text-top,middle,baseline,text-bottom,bottom等)文字太抽象,直接看(引數圖):

深度剖析Baseline設計原理
這張圖的資訊量比較大,我們一個一個的理解:

首先,當務之急是要理解,為什麼font-size都為100的情況下會出現高度不同的現象:(如圖中:第一個span的文字高度為164,而第二個高度則為100呢?)想要搞清楚這個問題,你必須要搞清楚字型是怎麼造出來的。因為字型的設計工作不是我們今天的主要工作,我們就直接用別人設計好的字型直接匯入字型設計工具。(這裡匯入的就是我們現在用的Catamaran字型。你可以在google的字型庫中找到這個字型https://github.com/qrpike/Web-Font-Load)

(2)字型是如何製造出來的

接下來就看一下字型是如何製造出來的,這你要去了解一個工具Fontforge,如何你有興趣研究,可以參考參考資料(1)快速入門。我們在這款字型工具中開啟M這個字型(O是一樣的)。

深度剖析Baseline設計原理

字型設計時,不出意外都是在上下1000units(font-size)這個單元格之間的範圍內設計。我們把上面的MO從新放回Fontforge工具中測試一下就這道。

深度剖析Baseline設計原理

相信看完這張圖,你一定了解了font-size的真正含義了. 但是到目前為止,你可能還有一個疑問就是:那為什麼用了Catamaran字型100px就是164畫素高呢? 到了這,有人可能就想研究一下fontforge了,所以這邊也貼出詳細的fontforge的使用說明參考:designwithfontforge.com/zh-CN/index…

@font-face {
       		 font-family: 'hhabnormal';
       		 src: url('./fontfamily/Catamaran.ttf') format('truetype');
   		 }複製程式碼

我們還是接著解決100px邊164畫素的問題。接下來我們把原生的Catamaran也與fontforge工具中的字型對比一下(你可以用以下程式碼在網頁中嘗試自己設計的字型)

深度剖析Baseline設計原理

對比上下兩張圖你會發現164px比100px,其實就是多出了font-size上下兩個問號的地方。那麼這兩個問號有指代什麼呢?對比上面提到的引數圖,你會發現有這樣的一塊區域,HHead/Win Ascent.這樣的兩個引數同樣是在設計字型的時候就定義好了的。你想通過CSS來修改是不可能的。這裡我們同樣用圖片進行對比,因為用圖片進行對比能讓你一目瞭然。我們來看一下,到底對原生的Catamaran字型做了什麼,讓它與原生的Catamaran字型高度上產生如此大的差異。

深度剖析Baseline設計原理 深度剖析Baseline設計原理

可能單看引數,很難理解其真實的含義,所以我們還是結合例項進行分析。我們把這些引數挨個的標註到字型中去。

深度剖析Baseline設計原理

對比著引數圖再看一下上面這張圖是不是很快就明白了為什麼設定了相同的font-size,卻表現出不同的高度。高出的部分其實是:

?(圖中上部)=Win/HHead Ascent - Type Ascent.

?(圖中下部)=Win/HHead Descent - Type Descent.

這裡有必要做一個解釋:Win Ascent使用在windows系統中的。HHead Ascent是用在Mac系統中的。基本上設計師在設計的時候兩者的值都時一樣的。之所以有兩個,是因為有兩個主流系統,並且他們又不按照同一個標準走,為了相容才這樣。

所以,我們現在算一下font-size:100px;一個高度表現為164px,一個高度表現為100px原因:

164px=Win/HHead Ascent(11px) +Win/HHead Descent(54px);

100px=Win/HHead Ascent(77px) +Win/HHead Descent(23px);

二、Baseline的位置

(1)不同display值的Baseline的位置

解決了上述font-size的疑問之後,一個新的疑問又誕生了:是所有的display型別的元素都有Baseline嗎?像inline-block這樣的元素如果有好幾行文字,是按第一行文字的baseline,還是按第二行文字的基線呢?比如如下圖:

深度剖析Baseline設計原理

像這樣的一個div盒模型中有兩行文字,那麼它的基線應該是按哪一條呢?為什麼要搞清楚這個問題?因為display:inline;display:inline-block;的元素都是按baseline來對齊的。不知道你寫的元素的baseline在哪,也就等於你寫的下一個元素出現在哪個位置,你根本不知道。來看一張圖你就明白了。

深度剖析Baseline設計原理

你會發現,但沒有一種對齊標準的時候,物品的擺放將顯得異常的混亂。所以這個時候,理解display:inline:display:inline-block;display:block;的基線在什麼位置就顯得格外的重要了。接下來分情況考慮:

(一)display:inline的基線

通過上面對字型的學習可以知道:inline的元素(如:span,label,i,等元素)的基線就是其中的元素的字型的基線。就是在第一節中的各種baseline.幾個不同的inline元素放在同一行的時候,就是把幾個的baseline對齊就可以了,就像上面的不同字號的“MO”按基線對齊後的排列是一樣的。

(二)display:inline-block的基線

我們用一個例項來看一下:

<div style="display:inline-block;width:100px;height:100px;word-wrap:break-word;
background-color: hsl(2, 86%, 58%);color:#fff;">
    <span>
        MOMOMOMOMOMOMOOMOM
    </span>
</div>
<span style="color:#fff">MOMO</span>複製程式碼

再來看一下執行的結果:

深度剖析Baseline設計原理

從圖中可以看出div元素的baseline是以其包含的inline元素的最後一行作為自己的baseline。下一個同一行中的元素將會把baseline與div的這條基線對齊。那麼所有的display:inline-block;都這樣嗎?像img這種的裡面沒有inline元素的怎麼辦呢?我們再通過一個例項來看一下。

<img src="http://chuantu.biz/t6/62/1506246890x3752257483.png" alt="" style="background-color:hsl(2, 86%, 58%);
height:100px;width:100px;">
<span style="color:#fff">MOMO</span>複製程式碼

看一下執行結果:

深度剖析Baseline設計原理

可以看出img的baseline是它的最底邊。其實看到這,我們大概也能得出一些結論了,就是display:inline-block;的元素的baseline。當其中有inline元素是按inline的baseline,當沒inline元素是,按最低邊。這樣總結對嗎?告訴你:基本是對的。不信,我們來看一下W3C對於inline-block的基線的定義:

The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge.

(三)display:block的基線

因為block元素是自己霸佔一行,所以它根本不需要基線,以為它不需要在前面或者後面與任何元素對齊。

(2)從vertical-align的值來了解Baseline的兄弟屬性的值的含義。
深度剖析Baseline設計原理

上面的那副引數圖,已經足以說明一切,除了沒有覆蓋到sub,super這種不太常用的屬性外,其他幾乎全覆蓋。每一個值都與上面的引數圖中一一對應,所以這一點就不再多說。

參考資料:

1.FontForge簡單使用教程:www.youtube.com/watch?v=ljR…

2.Deep dive CSS: font metrics, line-height and vertical-align iamvdo.me/en/blog/css…


相關文章