天天看點

line-height剖析

    1. 行高 line height的計算

    先得出結論:

    (1)line height指的并不是兩行中基線的距離

    (2)line height預設的值是normal,但是這個normal具體是多少和字型度量有關

    • 字型度量(font metrics):即字型的屬性和測量,包括ascender、descender、capital height、x-height 等。FontForge這個網站可以分析字型度量。
    line-height剖析

    (3)可以使用css進行字型度量的控制,但是需要計算。

    字型的原理:

    一款字型會定義一個 em-square,在傳統的雕版印刷中值得是金屬字模,現在指的是每個字元放置的空間容器,字模高度被稱作“em”,是空間的數字化定義總量,這是一個固定值,不同類型的字型不一緻,大緻有1000機關、1024機關、2048機關這幾種。

    line-height剖析
    假如我們使用的是Catamaran字型,在FontForge中查詢到的資訊如下
    line-height剖析

    這裡牽扯到不同的操作平台使用不同的參數:

    macOS 上的浏覽器使用了 HHead Ascent 和 HHead Descent 值,Windows 上的浏覽器使用了Win Ascent 和 Win Descent值,其實按理來說windows裡面應該是符合openType規範的,應該可以使用TypoAscent/TypoDescent的,是以windows的情況比較複雜。

    如何計算字型占用的實際大小(這裡等于HTML元素的content-area高度)呢?公式:(Ascent+Descent)/em-square*font-size。這裡是允許(Ascent+Descent)>em-square的。當設定font-size:100px;後,出現如下結果:

    line-height剖析

    可以計算出1ex = 49px; 1em = 100px;

    行高預設值怎麼計算呢(line-height:normal)?公式:(Ascent+Descent+Line Gap)/em-square*font-size。但是windows下可能會有點不一樣,有可能是:(Ascent+Descent)/em-square*font-size。詳情參考。設定為normal的時候,是告訴使用者代理(一般為浏覽器)根據元素的字型将所使用的值設定為一個“合理”值。這個值和line-height設定為number時意思一樣。w3推薦的值在1.0到1.2之間。後代元素會繼承縮放因子,即line-height為number的值,而不是繼承計算後的值。

    行高是怎麼定義的呢?   w3.org上面說的是:在一個内容由内聯級元素(inline-level element)組成的塊級容納元素(block container element),'line-height'指的是該元素中行盒(line boxes)的最小高度。這個最小高度包括基線(baseline)以上的最小高度(譯注:應該指的是ascent,用A表示)和基線以下的最小深度(譯注:應該指的是descent,用D表示),就像每個行盒以一個擁有元素字型(font)和行高(line height)屬性的零寬度行内盒(inline box)作為開頭。我們把這個想象的盒子叫“strut”。A和D在字型度量裡面定義;如果在一個非置換内聯元素上,line-height指的是被用來計算相應行盒高度的高度值。MDN上面的解釋  line-height會影響部分非置換元素的高度值。

    行盒的高度是由它所有的子元素的高度計算而來,具體來說就是從子元素的最高點到最低點的距離。行盒是看不見的,content-area也是看不見的。

    接下來有個概念叫vritual-area(官方文檔未對它進行定義),它的高度就是line-height的值

    line-height剖析

    點選打開連結

    是以”line-height 表示兩個 baseline 之間的距離“是不對的。

    virtual-area 和 content-area 高度的差異叫做 leading。leading 的一半會被加到 content-area 頂部,另一半會被加到底部。是以 content-area 總是處于 virtual-area 的中間。Leading就是行距。

    行高會被哪些因素影響?

    • 對于内聯元素,padding 和 border 會增大 background 區域,但是不會增大 content-area(不是 line-box 的高度)。一般來說你無法再螢幕上看到 content-area。margin-top 和 margin-bottom 對兩者都沒有影響。
    • 對于可替換内聯元素(replaced inline elements)、inline-block 元素和 blockified 内聯元素,padding、margin 和 border 會增大 height(譯者注:注意 margin),是以會影響 content-area 和 line-box 的高度。
      • 可替換的内聯元素,如 img / input / svg 等
      • inline-block 元素,以及所有 display 值以 inline- 開頭的元素,如 inline-table / inline-flex
      • 處于某種特殊格式化上下文的内聯元素,例如 flexbox 元素中的子元素都處于 flex formatting context(彈性格式化上下文)中,這些子元素的 display 值都是「blockified」

    這些元素的高度基于margin、border、height、padding。如果你将這些元素 height 設定為 auto 的話,那麼其高度的取值就是 line-height,其 content-area 的取值也是 line-height

    CSS雖然不能控制字型度量,但是可以圍繞它做一些事情。

    比如說,我們想要一段文字使用 Catamaran 字型,同時大寫字母的高度正好是 100px,看起來可以實作,我們隻需要一些數學知識。

    首先我們把所有字型度量設定為 CSS 自定義屬性,然後計算出一個 font-size,讓大寫字母的高度正好是 100px。

    p {

        --font: Catamaran;

        --fm-capitalHeight: 0.68;

        --fm-descender: 0.54;

        --fm-ascender: 1.1;

        --fm-linegap: 0;

        --capital-height: 100;

        font-family: var(--font);

        --computedFontSize: (var(--capital-height) / var(--fm-capitalHeight));

        font-size: calc(var(--computedFontSize) * 1px);

    }

    文字垂直居中也可以使用類似的方法

    知乎上面方應杭的譯文

    英文原文

    大漠老師的譯文