真的理解font-size和line-height了嗎?

希沃ENOW大前端css

公司官網:CVTE(廣州視源股份)html

團隊:CVTE旗下將來教育希沃軟件平臺中心enow團隊前端

本文做者:api

龍飛名片.png

前言

line-heightfont-size都是你們在平常開發過程當中常常用到的css屬性,可是有多少人知道fontsize設置100px,表明什麼意思呢? 它跟元素高度和line-height是什麼關係呢? 還有咱們常常將line-height設置父容器的高度來實現文本垂直居中對齊,它的原理是怎樣的呢,帶着這些問題,咱們來探討一下。瀏覽器

font-size

font-size其實表明的是字體的高度,若是不一樣的字體設置相同的font-size,字體高度會同樣麼,咱們來舉個例子看一下: 下面是一段簡單的 HTML 代碼,一個 p 標籤包含了 3 個 span 標籤,每一個 span 各自有一個 font-familymarkdown

<p>
    <span class="a">Ba</span>
    <span class="b">Ba</span>
    <span class="c">Ba</span>
</p>
p { font-size: 100px }
.a { font-family: Helvetica }
.b { font-family: Gruppo    }
.c { font-family: Catamaran }
複製代碼

font-size 相同,font-family 不一樣,結果發現獲得的 span 元素的高度也不一樣,通過測量發現: Helvetica 115px,Gruppo 97px,Catamaran 164pxoop

image.png

爲何會這樣呢,想要找到答案,咱們要先了解字體的原理。字體

字體原理

  1. 一款字體首先會定義一個em-square,它是用來盛放字符的金屬容器。這個 em-square 通常被設定爲寬高均爲 1000 相對單位,不過也能夠是 102四、2048 相對單位。你能夠理解爲字體的模板(字模),以下圖所示:

image.png

  1. 每一個字體會定義5條度量線來控制字符的位置,其中包括 ascender、descender、capital height、x-height,baseline 這5條度量線,這些度量的刻度是基於1000這個相對單位(不一樣字體相對單位可能不同)來設置的,以下圖所示:

image.png

  • Baseline: 就是咱們常說的基線,全部字母放置的水平線。它是文本中一條穩定的軸線,是校準文本與圖片,文本與文本的一條重要的參考線。其餘度量線都是相對基線來計算的。
  • X-Height: 是主要的小寫字母高度(或者說是「x」字母的高度),除去上延和下延部分
  • Cap Height: Capcapital(大寫字母)的簡稱,有時也用capital height全稱,是指H或E等直線型大寫字母從基線到字母頂部的高度(大寫字母高度)。而H或E等頂部這條對齊線叫做都大寫線(cap line
  • Ascender: 升部線,某些小寫字母(例如h、l)會有一個升部(也叫上延),高度超出x-height,這是升部的對齊線
  • Descender: 降部線,某些小寫字母(例如p、y)會有一個降部(也叫下延),沿基線往下延長的部分,這是降部的對齊線

其中,AscenderDescender之差決定了字體渲染的高度(不考慮行高),也就是下文將會提到的content-area(內容區域)的高度spa

  1. 在瀏覽器中,上面的 1000 相對單位會按照你須要的 font-size 縮放。

爲了作更好的分析,咱們裝一下FontForge軟件,看一下具體字體的字體度量信息。設計

具體的例子

FontForge軟件打開某個字體,通常咱們能夠看到這樣的設置:

image.png

Units Per Em(就是上文講到的em-square)表示一個字的高度有1000個單位,baseline的座標爲0,其它線的座標相對於baseline,以下圖所示:

image.png 不一樣字體的字體度量是不同的,咱們來分析一下上面例子用到的Catamaran字體: image.png

Em Size(也就是em-square): 1000,ascender : 1100,descender : 540macOS 上的瀏覽器使用了 HHead AscentHHead Descent 值,Windows 上的瀏覽器使用了 Win AscentWin Descent(並且兩個平臺上的值不同)。

這意味着 Catamaran 字體佔據了 1100 + 540 個相對單位,儘管它的 em-square 只有 1000 個相對單位,因此當咱們設置 font-size:100px 時,這個字體裏的文字高度是 1640*100/1000 = 164px ;另外咱們也能算出大寫字母的高度(cap height)是:680*100px/1000 = 68px;小寫字母的高度(x-height)是 485*100/1000=49px,以下圖所示:

image.png

總結

  1. fontsize 的值不表明字體高度,也不表明的字體內容(content-area)高度
  2. 字體內容(content-area)高度 與 font-sizefont-family 相關

line-height

line-height ,又稱行高,指的是兩行文字基線之間的距離,也能夠稱爲這行文字所佔的高度。

image.png 要理解line-height,咱們首先要先理解行內框盒子模型,如下咱們會詳細介紹具體的4種盒子。

行內框盒子模型

  1. 內容區域(content area):是一種圍繞文字看不見的盒子。內容區域的大小與font-size大小相關,也就是上文fontsize提到的AscenderDescender之間的高度,Ascender + Descender = conent-area的高度,以下圖所示:

image.png

  1. 內聯盒子(inline boxes):內聯盒子不會讓內容成塊顯示,而是排成一行。若是(文字)外部包含inline水平的標籤(span、a、em、strong等),則屬於內聯盒子。若是是個光禿禿的文字,則屬於匿名內聯盒子。圖示會更清楚,下圖紅色虛線框部分是匿名內聯盒子,實線框部分是內聯盒子:

image.png

  1. 行框盒子(line boxes):每一行就是一個行框盒子,每一個行框盒子又是由一個一個內聯盒子組成。
  2. 包含盒子(containing box):標籤所在的包含盒子是由一行一行的行框盒子組成。

具體的例子

咱們來考慮文本佔據的高度,見下例:

image.png

p標籤的高度從何而來呢,是由裏面的文字撐開的嗎?答案:不是的,實際上這個高度是由line-height決定的!再看下例:

image.png

經過此例說明,內聯元素的高度是由行高決定的!

至此,咱們能夠發現:

  1. 行高因爲其繼承性,影響無處不在,即便單行文本也不例外。
  2. 行高只是幕後黑手,高度的表現不是行高,而是內容區域行間距。也是就說,

內容區域高度(content area)+行間距(vertical spacing)=行高(line-height),其中行間距分上下部分,間距對半分。

注意:

  1. 內容區域(content area)高度只與字號(font-size)以及字體(font-size)有關,與line-height沒有任何關係。
  2. simsun字體(即宋體)下,內容區域高度等於文字大小值。因此,在simsun字體下,font-size+行間距=line-height。行間距上下拆分,就有了半行間距;例如在simsun字體下,font-size=240pxline-height=360px,則半行間距是:(360-240)/2 = 60px

若是line-height 小於font-sizeinline box會優先於行高,以保證inline box的高度正好等於行高。例:font-size: 16px; line-height: 12px; inline box高度爲12pxcontent area會溢出,inline box的頂部和底部半行高會摺疊起來,以保證inline box的高度。圖示以下:

image.png

對於行高,咱們得出如下結論:

一、行高 由 內容區域高度和行間距組成,行間距能夠爲負值,行間距分上下部分:上間距、下間距,它們距離相等。

二、行高用於計算 line-box 的高度

三、包含盒子的高度就是單行 line-box 高度的累加

屬性值表現

行高支持如下種類型的屬性值:

  • normal
  • 比例值,好比1.5
  • 具體長度值,好比1.5em
  • 百分比值,好比150%

一、normal

normal是默認屬性值,與字體相關聯,具體怎麼關聯呢,咱們使用FontForge軟件打開Catamaran字體來看一下:

image.png

  • 常規的 Ascent/Descent:ascender770,descender230,用於渲染字符。
  • 規格 Ascent/Descent:ascender1100,descender540。用於計算 content-area 的高度
  • 規格 Line Gap:用於計算 line-height: normal

Catamaran 這款字體中,Line Gap 的值是 0,那麼 line-height: normal 的結果就跟 content-area 的高度同樣,是 1640 相對單位。

爲了作對比,咱們再看看 Arial 字體,它的 em-square 是 2048ascender1854descender434line gap67。那麼當 font-size: 100px 時,

  • content-area 的高度就是 100/2048*(1854+434) = 111.72,約爲 112px
  • line-height: normal 的結果就是100/2048*(67+1854+434) 約爲 115px

全部這些值都是由字體設計師設置的。

二、比例值

使用比例值做爲行高值,例如line-height:1.5,這個比例值是相對當前元素的font-size來計算的, 假如font-size = 20px,那麼line-height = 1.5*20px = 30px

三、具體長度值

使用具體長度值做爲行高值,好比

  • line-height:1.5 rem/em(相對單位)
  • line-height:20px/pt(固定單位)

四、百分比值

使用百分比值做爲行高值,好比 line-height:150%,這個百分比也是相對當前元素的font-size,因此假如fontSize = 20px,那麼line-height = 1.5*20px = 30px

須要特別的注意的是,比例值和百分制從計算來看貌似沒什麼差異,可是最終效果是不同的,好比:

  • line-height:1.5,全部可繼承元素會本身的font-size從新計算行高,能夠理解爲只是繼承比例值。
  • line-height:150%,當前元素根據font-szie 計算行高後,會將這個值繼承給下面的元素,能夠理解爲繼承了具體的值。

舉個例子 ,看下面一段HTML代碼:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text /css"> div { line-height:1.5; font-size:24px; } p { font-size:60px; } </style>
</head>

<body>
    <div>
        <p>個人font-size
爲60px~</p>
    </div>
</body>

</html>
複製代碼

此時p標籤的行高爲:1.5×60 = 90px,兩行行框盒子高度爲180px

line-height:150%時,此時先計算 div 標籤的行高:150%×24 = 36px ,而後繼承給p標籤,因此兩行行框高度爲72px

後語

經過對font-sizeline-height的講解,相信你們都明天它們的含義了,回到前言提到的那個問題:line-height設置爲父容器的高度,爲什麼能讓文本垂直居中?我相信你們在閱讀完這篇文章應該已經有答案了吧。

相關文章
相關標籤/搜索