line-height vertical-align

原文出處:http://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align

  • 無授權(quán),基本上是翻譯原文,加上自己的理解和注釋赘风,當(dāng)做一個筆記拘央。
    作者說:這兩個屬性也許沒有看上去那么簡單,甚至是最難的之一。原因在于:內(nèi)聯(lián)格式化上下文(inline formating context)。
    因為我們對這兩個屬性知道的太少了,比如line-height:normal审胚,設(shè)置行高為正常,但是什么是正常呢礼旅?也許是1膳叨,也許是1.2,在字體這么多設(shè)置中痘系,它們的行為總是一樣嗎菲嘴?而且它們有什么影響嗎?

之后舉了一個font-size都是一樣的三個一樣標(biāo)簽的內(nèi)聯(lián)元素汰翠,字體不同龄坪,發(fā)現(xiàn)不一樣高,而且有一個高出了64px复唤。
font是根源所在:
1.一個字體(font)定義它的em-square(UPM ,unit per em)健田,類似于容器,每個字符都會被繪制佛纫。這個方形的容器使用相對單位妓局,一般設(shè)置為1000,但是它也可以是1024或者任何其他雳旅。
2.根據(jù)相對單位跟磨,可以設(shè)置上升下降(ascender,descender,capital height,x-height等等)间聊。一些值也有可能泄露在容器外面攒盈。
3.在瀏覽器中,相對單位被縮放以適合期望的字體大小哎榴。

這里作者用了一個軟件檢測字體的詳細指標(biāo)型豁。(https://fontforge.github.io/en-US/
上升+下降的值=字體em-square大小。
Mac OS上相對應(yīng)的是HHead Ascent / Descent值尚蝌,在Windows上使用Win Ascent / Descent值迎变,值也許會有不同。
比如一個ascent(上升)是1100飘言,descent(下降)是540衣形,em-square是1640,設(shè)置時的高度就是164px,這個計算的高度定義了一個元素的內(nèi)容區(qū)域谆吴。內(nèi)容區(qū)域視為屬性應(yīng)用的區(qū)域倒源。

  • 1ex是小寫字母,也就是對應(yīng)的x-height句狼,所以它是一個會變的數(shù)值笋熬,而不是像em基于font-size,而不是計算高度腻菇。
在原圖基礎(chǔ)上加了屬性方便查看

可以看到胳螟,它可以根據(jù)其寬度由許多線組成。每行由一個或多個內(nèi)聯(lián)元素(HTML標(biāo)簽或文本內(nèi)容的匿名內(nèi)聯(lián)元素)組成筹吐,稱為行框(line-box)糖耸,一個line-box是基于其子女的高度。
因此丘薛,瀏覽器計算每個內(nèi)嵌元素的高度蔬捷,并且因此定下line-box的高度(從其子的最高點到其子的最低點)。因此榔袋,行框總是足夠高以包含其所有子項(默認情況下)周拐。
其實知道每個line-box的高度,就知道一個元素的高度凰兑。

但是實際是看不到line-box的妥粟,也不能用CSS控制它,設(shè)置個背景也沒有多大用處吏够。

<b>line-height:to the problems and beyond</b>

一個line-box的高度由孩子的height計算勾给,沒有說它孩子content-area的高度。這產(chǎn)生了很大的區(qū)別锅知。

即使它可能聽起來很奇怪播急,一個內(nèi)聯(lián)元素有兩個不同的高度:內(nèi)容區(qū)域高度(content-area)和虛擬區(qū)域(virtual-area )高度(作者發(fā)明了術(shù)語虛擬區(qū)域O__O "…)。
1.在內(nèi)容區(qū)高度(content-area)由字體規(guī)格(font metrics)定義(如前所示)
2.在虛擬區(qū)域的高度是line-height售睹,它的高度用于計算line-box的高度(it is the height used to compute the line-box’s height)

計算出的虛擬區(qū)域和內(nèi)容區(qū)域之間的高度差稱為leading桩警。一半leading被添加在內(nèi)容區(qū)域的頂部,另一半被添加在底部昌妹。因此捶枢,內(nèi)容區(qū)域總是在虛擬區(qū)域的中間。
基于其計算值飞崖,line-height(虛擬區(qū)域)可以等于烂叔,高于或小于內(nèi)容區(qū)域。在較小的虛擬區(qū)域的情況下固歪,leading是負的蒜鸡,并且line-box在視覺上小于其孩子。
還有其他種類的內(nèi)聯(lián)元素:

取代內(nèi)聯(lián)元素(<圖片>,<input>逢防,<svg>等)
inline-block和所有inline-*元素
參與特定格式化上下文的內(nèi)聯(lián)元素(例如康聂,在flexbox元素中,所有flex項目都被塊化)
對于這些特定的內(nèi)聯(lián)元素胞四,高度的計算基于他們的height恬汁,margin和border屬性。如果height是auto辜伟,則line-height使用并且內(nèi)容區(qū)域嚴格等于line-height氓侧。

上圖!同樣是原作者的圖 ![Uploading line-height-yes-no_400235.png . . .]

之后是討論了兩種字體的line-height:1导狡,發(fā)現(xiàn)內(nèi)容區(qū)域不一樣大约巷,
<b>很明顯,設(shè)置line-height: 1是一個壞的做法旱捧。</b>
無單位的值是font-size相對的独郎,而不是內(nèi)容區(qū)域相對的,并且處理小于內(nèi)容區(qū)域的虛擬區(qū)域是我們的許多問題的起源枚赡。
并且作者發(fā)現(xiàn)在1117中字體中1059字體氓癌,大約95%,有一個line-height計算大于1.他們的計算從0.618到3.378贫橙。

<b>vertical-align:one property to rule them all</b>

奇怪的是贪婉,默認的基線對齊可能會導(dǎo)致更高的(!)行框卢肃,一個行框的高度是從它的孩子的最高點到它的孩子的最低點計算的疲迂。

繼承的font-family可能不是想象中的大小,因為每個標(biāo)簽的基準(zhǔn)(baseline)很可能是不同的莫湘,所描述的line-box高于預(yù)期尤蒿。因為瀏覽器計算每個line-box都是以0寬度開始的,稱為strut幅垮。(This happens because browsers do their computation as if each line-box starts with a zero-width character , that the spec called a strut.)

規(guī)范是這么寫middle的 “aligns the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent”腰池,基線比不同,x-height比也不同军洼,使用align也不可靠巩螃。middle不是真的在中間。

vertical-align: top / bottom align to the top or the bottom of the line-box

vertical-align: text-top / text-bottom align to the top or the bottom of the content-area

依舊是原博客圖

注意匕争,在所有情況下,它對齊虛擬區(qū)域爷耀,因此是不可見的高度甘桑。看看這個使用vertical-align: topline-height的例子∨芎迹看不見可能產(chǎn)生奇怪铆帽,但不令人驚訝的結(jié)果。

我說怎么對不齊呢

最后德谅,vertical-align還接受提高或降低關(guān)于基線的數(shù)值爹橱。最后一個選項可能派上用場。

<b>CSS is awesome</b>

我們已經(jīng)討論過如何讓line-height和vertical-align一起工作窄做,但現(xiàn)在的問題是:字體指標(biāo)可以用CSS控制嗎愧驱?
簡答:不。
字體指標(biāo)是不變的椭盏,所以我們應(yīng)該能夠做一些事情组砚。

例如,如果我們想要一個使用 Catamaran的文本掏颊,其中captical-height正好是100px高糟红?
看起來可行:讓我們做一些數(shù)學(xué)。

首先乌叶,我們將所有字體指標(biāo)設(shè)置為CSS自定義屬性盆偿,然后計算font-size獲得100px的captical-height。

p { 
/* font metrics */ 
--font: Catamaran;
--capitalHeight: 0.68;   
--descender: 0.54; 
--ascender: 1.1; 
--linegap: 0;

/* desired font-size for capital height */ 
--fontSize: 100;

/* apply font-family */ 
font-family: var(--font);

/* compute font-size to get capital height equal desired font-size */ 
--computedFontSize: (var(--fontSize) / var(--capitalHeight));
font-size: calc(var(--computedFontSize) * 1px);
}

很簡單准浴,不是嗎陈肛?但是,如果我們想讓文本在視覺上位于中間兄裂,以便剩余的空間平均分布在“B”字母的頂部和底部句旱?為了實現(xiàn)這一點,我們必須vertical-align根據(jù)上升/下降比率來計算晰奖。
首先谈撒,計算和內(nèi)容區(qū)域的高度:line-height: normal

p {
    …
    --lineheightNormal: (var(--ascender) + var(--descender) + var(--linegap));
   --contentArea: (var(--lineheightNormal) * var(--computedFontSize));
}

然后需要:

the distance from the bottom of the capital letter to the bottom edge
the distance from the top of the capital letter to the top edge

像這樣:

p {
    …
    --distanceBottom: (var(--descender));
    --distanceTop: (var(--ascender) - var(--capitalHeight));
}

我們現(xiàn)在可以計算vertical-align,這是乘以計算的距離之間的差異font-size( which is the difference between the distances multiplied by the computed font-size這句啥意思匾南?啃匿?)。(我們必須將此值應(yīng)用于內(nèi)聯(lián)子元素)

p {
    …
    --valign: ((var(--distanceBottom) - var(--distanceTop)) * var(--computedFontSize));
}
span {
    vertical-align: calc(var(--valign) * -1px);
}

最后蛆楞,我們設(shè)置所需的line-height并計算它溯乒,同時保持垂直對齊:

p {
    …
    /* desired line-height */
    --lineheight: 3;
    line-height: calc(((var(--lineheight) * var(--fontSize)) - var(--valign)) * 1px);
}

結(jié)果就是特別完美的居中。圖就是傳不上來……

注意豹爹,此測試僅用于演示目的裆悄。
你不能依賴這個。

很多原因:

除非字體指標(biāo)是不變的臂聋,瀏覽器中的計算不是光稼。
如果字體未加載或南,則后備字體可能具有不同的字體度量,并且處理多個值將很快變得非常難以管理艾君。

<b>Takeaways</b>

我們學(xué)到了什么:

  • 內(nèi)聯(lián)格式化上下文真的很難理解

  • 所有內(nèi)聯(lián)元素都有2個高度:

  • 內(nèi)容區(qū)域content-area(根據(jù)字體規(guī)格)

  • 虛擬區(qū)域virtical-area(line-height)

  • 這2個高度中沒有一個可以可視化采够,毫無疑問。
    (如果你是一個devtools開發(fā)人員冰垄,想要工作蹬癌,這可能是真棒)

  • line-height: normal 是基于字體度量

  • line-height: n可以創(chuàng)建小于內(nèi)容區(qū)域虛擬區(qū)域

  • vertical-align 不是很可靠

  • 一個line-box的高度是根據(jù)它的孩子們的line-height和vertical-align
    屬性來計算

  • 我們不能很容易地獲取/設(shè)置CSS的字體指標(biāo)

  • 有一個相關(guān)的未來規(guī)范來幫助垂直對齊:線網(wǎng)格模塊

但我還是喜歡CSS :)

后記:沒想到花了好幾個小時,很佩服原作者這種默默的奉獻虹茶,他一定花了比我更多的時間去寫逝薪,去做圖讓讀者更好理解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末写烤,一起剝皮案震驚了整個濱河市翼闽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洲炊,老刑警劉巖感局,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暂衡,居然都是意外死亡询微,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門狂巢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撑毛,“玉大人,你說我怎么就攤上這事唧领≡宕疲” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵斩个,是天一觀的道長胯杭。 經(jīng)常有香客問我,道長受啥,這世上最難降的妖魔是什么做个? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮滚局,結(jié)果婚禮上居暖,老公的妹妹穿的比我還像新娘。我一直安慰自己藤肢,他們只是感情好太闺,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谤草,像睡著了一般跟束。 火紅的嫁衣襯著肌膚如雪莺奸。 梳的紋絲不亂的頭發(fā)上丑孩,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天冀宴,我揣著相機與錄音,去河邊找鬼温学。 笑死略贮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仗岖。 我是一名探鬼主播逃延,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼轧拄!你這毒婦竟也來了揽祥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤檩电,失蹤者是張志新(化名)和其女友劉穎拄丰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俐末,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡料按,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卓箫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片载矿。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖烹卒,靈堂內(nèi)的尸體忽然破棺而出闷盔,到底是詐尸還是另有隱情,我是刑警寧澤旅急,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布逢勾,位于F島的核電站,受9級特大地震影響坠非,放射性物質(zhì)發(fā)生泄漏敏沉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一炎码、第九天 我趴在偏房一處隱蔽的房頂上張望盟迟。 院中可真熱鬧,春花似錦潦闲、人聲如沸攒菠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辖众。三九已至卓起,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凹炸,已是汗流浹背戏阅。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留啤它,地道東北人奕筐。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像变骡,于是被迫代替她去往敵國和親离赫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案塌碌? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J的外補...
    _Yfling閱讀 13,754評論 1 92
  • 有些東西我們經(jīng)常用渊胸,但是我們卻并不了解它的原理,所以一旦換了場景台妆,好多東西就不知道該怎么用了翎猛。最近一直很糾結(jié)ver...
    朱小維閱讀 4,935評論 8 34
  • 參考文章:深入了解CSS的line-height屬性Vertical-Align: 你需要知道的所有事【譯】Ver...
    若邪Y閱讀 3,440評論 1 6
  • 前言 總括: 本文通過實例講解CSS中最大的難點之一,行內(nèi)元素的布局频丘,主要是挖掘line-height和verti...
    秦至閱讀 1,915評論 0 1
  • 人生若只如初見 何事秋風(fēng)悲畫扇 等閑變卻故人心 卻道故人心易變 驪山語罷清霄半 淚雨零鈴終不怨 如何薄幸錦衣郎 比...
    CXY_CXY閱讀 91評論 0 1