在終端或網(wǎng)頁項目中艇挨,有時候驗收 UI 時會發(fā)現(xiàn)文字的行間距會比設(shè)定的更大残炮,和開發(fā)多次核對后得知,這是因為文字控件本身帶有內(nèi)padding缩滨,再加上設(shè)定的行距势就,視覺效果相當于是 padding 和 margin 疊加了。
而padding到底是多少呢脉漏?代碼里是看不到的苞冯,sketch也看不到具體數(shù)值,不過可以通過字號和文字實際占用高度(即拖黑區(qū)域)來比較侧巨,通過控制字體包和字號兩個變量舅锄。
前三個字體統(tǒng)一30px字號,行高分別為 1.4倍司忱、1倍皇忿、1.5倍,而將最后一個字體包的字號改為20烘贴,行高又變成了1.45倍禁添,說明不僅是不同字體行高不同,就連相同字體的不同字號桨踪,行高也并不是一個固定的倍數(shù)。
注:思源黑體在 Adobe 體系里稱為思源字體 Source Han Sans锻离,在 Google 體系里被納為 Noto 字體體系一部分,字體包叫做 Noto Sans CJK SC 墓怀,兩個版本字形和基線完全一致汽纠,區(qū)別在于行高和字重設(shè)定,這就導致在屏顯文字的應(yīng)用中傀履,兩個版本幾乎要當作兩種字體來處理虱朵。
值得一提的是,這個問題很早就被其他同事注意到(再往前一般是被當作玄學問題,只從操作層面解決碴犬,沒有找到根本原因)絮宁,當時經(jīng)手的同事就猜測和字體包有關(guān),只是還缺少更多細節(jié)服协。不過實踐上已經(jīng)可以解決問題:
-
非系統(tǒng)自帶的第三方應(yīng)用绍昂,除非自己打進一套字體,不然并不能控制不同終端的系統(tǒng)字體偿荷,所以設(shè)計稿推薦使用帶一定行高的字體(除了source開頭的思源黑體窘游,其他的都可以),并允許小范圍的系統(tǒng)性誤差跳纳。移動端為iOS和安卓系統(tǒng)分別制作了兩套字體規(guī)范忍饰,因為蘋方和思源黑體的行高有差異,分別兩套可以精細化控制排版寺庄。
移動端字體規(guī)范局部(iOS和安卓各一套) 和固件配套的系統(tǒng)應(yīng)用喘批,我們正好可以控制固件中打入的系統(tǒng)字體。但固件自帶的黑體不一定全是 noto開頭的铣揉,有些可能因為歷史原因饶深,打入了source開頭的,所以調(diào)試和出貨之前要統(tǒng)一確認是否打入了 noto 開頭的字體逛拱。(下圖為安卓原生固件中的字體敌厘,中文是NotoSansCJK-regular.ttc, ttc格式包含了多種字重,調(diào)用ttc字重的方法略)
source開頭的黑體不建議用作終端應(yīng)用的字體朽合,因為它不帶內(nèi)padding俱两,行高=1倍,如果不特別設(shè)定行間距曹步,就會顯得很密集宪彩,即使軟件針對source字體做了排版優(yōu)化,一跨平臺又會出現(xiàn)更大偏差讲婚。
做UI稿一定不能用PS尿孔,因為PS在識別文字間距時,會以實際像素覆蓋的區(qū)域為邊界筹麸,相當于所有文字都變成padding=0活合,行高=1倍。
部分瀏覽器在渲染文字時會再次增加行高物赶,需注意驗收界面實際效果白指。
那這個問題還有什么沒弄清楚的細節(jié)呢?留意上圖中第三個思源黑體酵紫,在接近字底部的地方有一條藍色線:
這是鼠標懸浮時被軟件標記的線告嘲,重新打一段中英混排的文本错维,就知道這條線原來就是英文的基線:
眾所周知,英文字母的排列遵循三條參考線:基線橄唬、小寫線赋焕、大寫線,其中小寫線也叫x線轧坎,大寫線也叫升部線宏邮,有升部就有降部,比如小寫字母 j 缸血,下面超出基線的部分就叫降部了(當然要細分并不止這3條線)蜜氨。英文的視覺重心在基線到x線之間的區(qū)域,大寫字母橫跨基線和升部之間的區(qū)域捎泻,所以整體重心會在x區(qū)域偏上一點飒炎。
中文的視覺重心邏輯不一樣,中文的重心是中宮笆豁,中宮大約是文字中心1/3的區(qū)域郎汪。古文是豎排的,豎排時字的高矮沒有要求闯狱,而寬窄變化煞赢,只要中宮對齊,外圍收一點放一點也是可以的『骞拢現(xiàn)代漢語為了與其他語種(文化)銜接照筑,改為了橫排。如果依舊遵循中宮對齊瘦陈,文字本身的高矮變化都會造成視線的起伏凝危,增加閱讀障礙。所以古早時期晨逝,中文在改橫排時蛾默,就對一部分過于簡單的文字進行了結(jié)構(gòu)微調(diào),比如把“心”字縱向拉高捉貌,達到縱向上量感勻稱支鸡。
多語言混排時,如果直接讓中文的中宮和英文的x區(qū)域等高并對齊昏翰,視覺上更加顯得英文量感偏小苍匆、重心偏上了。
那文字混排時究竟應(yīng)該遵循什么規(guī)則棚菊?特別是在多語種全球化、標準化過程中叔汁,屏顯字體在設(shè)計時有沒有什么公理呢统求?
先sketch打三段文本检碗,用思源黑體 noto 版本打一段中文和英文漂佩,再用 roboto 同等字號打一段(yhx三個字母表示升部降部)仲吏。為了準確顯示行高已慢,因此三段文本是各自獨立的文字控件何之。之前混排打字時得知崖叫,sketch會顯示所有文字的基線端考,并且共享同一條基線哨苛,所以這里也讓三個文字控件基線對齊幢码。
字號 28己莺, 用彩色塊沿基線畫出 28 的高度奏甫;發(fā)現(xiàn)色塊高度全部比文字的本體都高,也就是文字的筆畫不會超出字號所占的像素高度凌受;灰色塊是文字控件占用的高度阵子,即“行高”,也是選中拖黑的高度胜蛉∧咏灰色塊的高度全部大于彩色塊的高度。
再把能標的參考線都標出來誊册,共享的基線领突;英文的x線、升部線案怯、降部線君旦。剛剛說不止這幾條,有些字母上端會超出升部線(案例里剛好沒有)殴泰,所以升部線以上還有上升線于宙,降部線以下還有下降線,上升線和下降線在哪里悍汛,會不會剛好就是灰色區(qū)域的邊界捞魁?
另外注意到,中文筆畫中的撇离咐、揦谱俭、豎、勾均會稍稍超出基線宵蛀,而橫卻剛好貼著基線昆著。也就是說中文字最底端的橫畫被標記為基線,用來替代中宮與英文對齊术陶。橫排文字中的基線可以作為視線引導凑懂,它是文字的內(nèi)骨骼。中文撇梧宫、揦接谨、豎摆碉、勾這些外延性的筆畫會比基線更低,正好對應(yīng)了英文中的降部脓豪。
為了進一步探索行高和參考線的關(guān)聯(lián)巷帝,我發(fā)現(xiàn)了另一個厲害的工具 【 字體熔爐】——Font Forge
作為一個設(shè)計字體的工具,可以從微觀角度展示字體文件的內(nèi)部結(jié)構(gòu)扫夜。
下圖左邊是用 Font Forge 畫出來的字母 y楞泼,界面中也有顯示 acender 上升線,descender 下降線笤闯。定義基線的高度為0堕阔。繪制文字的畫布區(qū)域為 1000 unit。
那升部和降部呢望侈?此刻他們分別等于上升線和下降線的值印蔬,所以上升線和下降線之間的距離剛好等于畫布區(qū)域,也就是1000脱衙。此刻設(shè)計出來的英文字體就是兩頭貼邊的侥猬。
右邊為打開的屬性, cap-height即大寫線(升部線)捐韩。
下圖為知乎用戶李銀城 制作的字體退唠,網(wǎng)頁上顯示可見,不論多大的字體 荤胁,上下都貼邊瞧预,也就是沒有padding。這里是用的英文測試仅政,如果換成中文垢油,根據(jù)在 sketch 上的試驗,可以推測中文不會完全貼邊(貼升部線和降部線)圆丹,思源黑體source版本確實筆畫也沒有貼邊滩愁,但彩色區(qū)域必定是等于灰色區(qū)域的(即行高=字號等額像素高度)。
那市面上正規(guī)的字體打開是怎樣的呢辫封?
1415/1000 硝枉,剛好等于1.4倍的行高。這也就解釋了之前的現(xiàn)象倦微,字體自帶 1.2-1.4的行高妻味,這與終端設(shè)定的排版格式無關(guān),只與字族本身的屬性有關(guān)欣福。
那前端還可以控制嗎责球?也可以,甚至可以設(shè)定比字體本身的更小的行高,所以有時候同一個網(wǎng)站在不同瀏覽器中顯示的行高有區(qū)別棕诵。