關(guān)于屏顯文字行高和基線(xiàn)問(wèn)題的研究

在終端或網(wǎng)頁(yè)項(xiàng)目中,有時(shí)候驗(yàn)收 UI 時(shí)會(huì)發(fā)現(xiàn)文字的行間距會(huì)比設(shè)定的更大,和開(kāi)發(fā)多次核對(duì)后得知,這是因?yàn)槲淖挚丶旧韼в袃?nèi)padding,再加上設(shè)定的行距,視覺(jué)效果相當(dāng)于是 padding 和 margin 疊加了。

而padding到底是多少呢?代碼里是看不到的,sketch也看不到具體數(shù)值,不過(guò)可以通過(guò)字號(hào)和文字實(shí)際占用高度(即拖黑區(qū)域)來(lái)比較,通過(guò)控制字體包和字號(hào)兩個(gè)變量。

前三個(gè)字體統(tǒng)一30px字號(hào),行高分別為 1.4倍、1倍、1.5倍,而將最后一個(gè)字體包的字號(hào)改為20,行高又變成了1.45倍,說(shuō)明不僅是不同字體行高不同,就連相同字體的不同字號(hào),行高也并不是一個(gè)固定的倍數(shù)。

不同字體包、不同字號(hào)的行高對(duì)比

注:思源黑體在 Adobe 體系里稱(chēng)為思源字體 Source Han Sans,在 Google 體系里被納為 Noto 字體體系一部分,字體包叫做 Noto Sans CJK SC ,兩個(gè)版本字形和基線(xiàn)完全一致,區(qū)別在于行高和字重設(shè)定,這就導(dǎo)致在屏顯文字的應(yīng)用中,兩個(gè)版本幾乎要當(dāng)作兩種字體來(lái)處理。

值得一提的是,這個(gè)問(wèn)題很早就被其他同事注意到(再往前一般是被當(dāng)作玄學(xué)問(wèn)題,只從操作層面解決,沒(méi)有找到根本原因),當(dāng)時(shí)經(jīng)手的同事就猜測(cè)和字體包有關(guān),只是還缺少更多細(xì)節(jié)。不過(guò)實(shí)踐上已經(jīng)可以解決問(wèn)題:

  1. 非系統(tǒng)自帶的第三方應(yīng)用,除非自己打進(jìn)一套字體,不然并不能控制不同終端的系統(tǒng)字體,所以設(shè)計(jì)稿推薦使用帶一定行高的字體(除了source開(kāi)頭的思源黑體,其他的都可以),并允許小范圍的系統(tǒng)性誤差。移動(dòng)端為iOS和安卓系統(tǒng)分別制作了兩套字體規(guī)范,因?yàn)樘O(píng)方和思源黑體的行高有差異,分別兩套可以精細(xì)化控制排版。


    移動(dòng)端字體規(guī)范局部(iOS和安卓各一套)
  2. 和固件配套的系統(tǒng)應(yīng)用,我們正好可以控制固件中打入的系統(tǒng)字體。但固件自帶的黑體不一定全是 noto開(kāi)頭的,有些可能因?yàn)闅v史原因,打入了source開(kāi)頭的,所以調(diào)試和出貨之前要統(tǒng)一確認(rèn)是否打入了 noto 開(kāi)頭的字體。(下圖為安卓原生固件中的字體,中文是NotoSansCJK-regular.ttc, ttc格式包含了多種字重,調(diào)用ttc字重的方法略)

找固件開(kāi)發(fā)大哥挖掘的信息
  1. source開(kāi)頭的黑體不建議用作終端應(yīng)用的字體,因?yàn)樗粠?nèi)padding,行高=1倍,如果不特別設(shè)定行間距,就會(huì)顯得很密集,即使軟件針對(duì)source字體做了排版優(yōu)化,一跨平臺(tái)又會(huì)出現(xiàn)更大偏差。

  2. 做UI稿一定不能用PS,因?yàn)镻S在識(shí)別文字間距時(shí),會(huì)以實(shí)際像素覆蓋的區(qū)域?yàn)檫吔?,相?dāng)于所有文字都變成padding=0,行高=1倍。

  3. 部分瀏覽器在渲染文字時(shí)會(huì)再次增加行高,需注意驗(yàn)收界面實(shí)際效果。

那這個(gè)問(wèn)題還有什么沒(méi)弄清楚的細(xì)節(jié)呢?留意上圖中第三個(gè)思源黑體,在接近字底部的地方有一條藍(lán)色線(xiàn):

hover線(xiàn)

這是鼠標(biāo)懸浮時(shí)被軟件標(biāo)記的線(xiàn),重新打一段中英混排的文本,就知道這條線(xiàn)原來(lái)就是英文的基線(xiàn):

中英混排的hover線(xiàn)

眾所周知,英文字母的排列遵循三條參考線(xiàn):基線(xiàn)、小寫(xiě)線(xiàn)、大寫(xiě)線(xiàn),其中小寫(xiě)線(xiàn)也叫x線(xiàn),大寫(xiě)線(xiàn)也叫升部線(xiàn),有升部就有降部,比如小寫(xiě)字母 j ,下面超出基線(xiàn)的部分就叫降部了(當(dāng)然要細(xì)分并不止這3條線(xiàn))。英文的視覺(jué)重心在基線(xiàn)到x線(xiàn)之間的區(qū)域,大寫(xiě)字母橫跨基線(xiàn)和升部之間的區(qū)域,所以整體重心會(huì)在x區(qū)域偏上一點(diǎn)。

中文的視覺(jué)重心邏輯不一樣,中文的重心是中宮,中宮大約是文字中心1/3的區(qū)域。古文是豎排的,豎排時(shí)字的高矮沒(méi)有要求,而寬窄變化,只要中宮對(duì)齊,外圍收一點(diǎn)放一點(diǎn)也是可以的?,F(xiàn)代漢語(yǔ)為了與其他語(yǔ)種(文化)銜接,改為了橫排。如果依舊遵循中宮對(duì)齊,文字本身的高矮變化都會(huì)造成視線(xiàn)的起伏,增加閱讀障礙。所以古早時(shí)期,中文在改橫排時(shí),就對(duì)一部分過(guò)于簡(jiǎn)單的文字進(jìn)行了結(jié)構(gòu)微調(diào),比如把“心”字縱向拉高,達(dá)到縱向上量感勻稱(chēng)。

多語(yǔ)言混排時(shí),如果直接讓中文的中宮和英文的x區(qū)域等高并對(duì)齊,視覺(jué)上更加顯得英文量感偏小、重心偏上了。

在中文中標(biāo)出英文的x線(xiàn)

那文字混排時(shí)究竟應(yīng)該遵循什么規(guī)則?特別是在多語(yǔ)種全球化、標(biāo)準(zhǔn)化過(guò)程中,屏顯字體在設(shè)計(jì)時(shí)有沒(méi)有什么公理呢?

先sketch打三段文本,用思源黑體 noto 版本打一段中文和英文,再用 roboto 同等字號(hào)打一段(yhx三個(gè)字母表示升部降部)。為了準(zhǔn)確顯示行高,因此三段文本是各自獨(dú)立的文字控件。之前混排打字時(shí)得知,sketch會(huì)顯示所有文字的基線(xiàn),并且共享同一條基線(xiàn),所以這里也讓三個(gè)文字控件基線(xiàn)對(duì)齊。

參考線(xiàn)圖解

字號(hào) 28, 用彩色塊沿基線(xiàn)畫(huà)出 28 的高度;發(fā)現(xiàn)色塊高度全部比文字的本體都高,也就是文字的筆畫(huà)不會(huì)超出字號(hào)所占的像素高度;灰色塊是文字控件占用的高度,即“行高”,也是選中拖黑的高度。灰色塊的高度全部大于彩色塊的高度。

再把能標(biāo)的參考線(xiàn)都標(biāo)出來(lái),共享的基線(xiàn);英文的x線(xiàn)、升部線(xiàn)、降部線(xiàn)。剛剛說(shuō)不止這幾條,有些字母上端會(huì)超出升部線(xiàn)(案例里剛好沒(méi)有),所以升部線(xiàn)以上還有上升線(xiàn),降部線(xiàn)以下還有下降線(xiàn),上升線(xiàn)和下降線(xiàn)在哪里,會(huì)不會(huì)剛好就是灰色區(qū)域的邊界?

另外注意到,中文筆畫(huà)中的撇、揦、豎、勾均會(huì)稍稍超出基線(xiàn),而橫卻剛好貼著基線(xiàn)。也就是說(shuō)中文字最底端的橫畫(huà)被標(biāo)記為基線(xiàn),用來(lái)替代中宮與英文對(duì)齊。橫排文字中的基線(xiàn)可以作為視線(xiàn)引導(dǎo),它是文字的內(nèi)骨骼。中文撇、揦、豎、勾這些外延性的筆畫(huà)會(huì)比基線(xiàn)更低,正好對(duì)應(yīng)了英文中的降部。

為了進(jìn)一步探索行高和參考線(xiàn)的關(guān)聯(lián),我發(fā)現(xiàn)了另一個(gè)厲害的工具 【 字體熔爐】——Font Forge
作為一個(gè)設(shè)計(jì)字體的工具,可以從微觀角度展示字體文件的內(nèi)部結(jié)構(gòu)。

下圖左邊是用 Font Forge 畫(huà)出來(lái)的字母 y,界面中也有顯示 acender 上升線(xiàn),descender 下降線(xiàn)。定義基線(xiàn)的高度為0。繪制文字的畫(huà)布區(qū)域?yàn)?1000 unit。
那升部和降部呢?此刻他們分別等于上升線(xiàn)和下降線(xiàn)的值,所以上升線(xiàn)和下降線(xiàn)之間的距離剛好等于畫(huà)布區(qū)域,也就是1000。此刻設(shè)計(jì)出來(lái)的英文字體就是兩頭貼邊的。
右邊為打開(kāi)的屬性, cap-height即大寫(xiě)線(xiàn)(升部線(xiàn))。

字體包含的屬性

下圖為知乎用戶(hù)李銀城 制作的字體,網(wǎng)頁(yè)上顯示可見(jiàn),不論多大的字體 ,上下都貼邊,也就是沒(méi)有padding。這里是用的英文測(cè)試,如果換成中文,根據(jù)在 sketch 上的試驗(yàn),可以推測(cè)中文不會(huì)完全貼邊(貼升部線(xiàn)和降部線(xiàn)),思源黑體source版本確實(shí)筆畫(huà)也沒(méi)有貼邊,但彩色區(qū)域必定是等于灰色區(qū)域的(即行高=字號(hào)等額像素高度)。

使用自創(chuàng)的字體來(lái)測(cè)試行高

那市面上正規(guī)的字體打開(kāi)是怎樣的呢?

正規(guī)字體包的屬性
字體設(shè)計(jì)界面和參考線(xiàn)

1415/1000 ,剛好等于1.4倍的行高。這也就解釋了之前的現(xiàn)象,字體自帶 1.2-1.4的行高,這與終端設(shè)定的排版格式無(wú)關(guān),只與字族本身的屬性有關(guān)。
那前端還可以控制嗎?也可以,甚至可以設(shè)定比字體本身的更小的行高,所以有時(shí)候同一個(gè)網(wǎng)站在不同瀏覽器中顯示的行高有區(qū)別。

參考:
字號(hào)與行高
前端基礎(chǔ)系列之字體初探

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容