CSS中line-height與vertical-align

參考文章:
深刻了解CSS的line-height屬性
Vertical-Align: 你須要知道的全部事【譯】
Vertical-Align: All You Need To Knowhtml

一、什麼是行間距或者行高(line-height)

line-height是指文本行基線間的垂直距離。瀏覽器

1.一、頂線,中線,基線,底線

從上到下分別是頂線,中線,基線,底線。vertical-align的四個屬性top,middle,baseline,bottom就是與這四條線有關。佈局

1.二、行高,行距,半行距

  • 行高是指上下文本行基線間的垂直距離。(上圖中兩條紅線間的垂直距離)
  • 行距是指一行底線到下一行頂線的垂直距離。(第一條粉線和第二條綠線間的垂直距離)
  • 半行距就是行距/2。(圖中能夠看出,半行距=(行高-字體size)/2 )

1.三、內容區,行內框,行框

  • 內容區:頂線和底線包裹的區域(字體的size)
  • 行內框:在沒有其餘因素影響的時候(padding等),行內框等於內容區。而設定行高時行內框高度不變,半行距分別增長/減小到內容區的上下兩邊(深藍色區域)行框(line box)。(字體size不變,修改行高就是修改行距)
  • 行框:行框高度等於本行內全部元素中行內框最大的值(以行高值最大的行內框爲基準,其餘行內框採用本身的對齊方式向基準對齊,最終計算行框的高度),當有多行內容時,每行都會有本身的行框。

1.四、line-height的設置

百分比方式設置字體

<body>
  121212
  <p>121212</p>
</body>
body{
  font-size:16px;
  line-height:120%;
}
p{
  font-size:32px;
}

line-height的百分比(120%)和body的字體大小(16px),被用來計算(16*120=19.2),這個值會被層疊下去的元素所繼承。
spa

補充.net

p{
  font-size:32px;
  line-height:60px;
  padding:10px
}

最終盒模型3d

盒模型中,內容(不是上文說的內容區,上文的內容區是頂線與底線間的區域)的高度等於line-height的值。爲何會有margin?瀏覽器默認P的上下margin是1em,設置了P的font-size是32px,因此1em=32px。上下margin就是32px。code

長度方式(px)設置orm

<body>
  121212
  <p>121212</p>
</body>
body{
  font-size:16px;
  line-height:20px;
}
p{
  font-size:32px;
}

值normalhtm

<body>
  121212
  <p>121212</p>
</body>
body{
  font-size:16px;
  line-height:normal;
}
p{
  font-size:32px;
}

body

body的line的line-height是22px,因此normal等於1.375

p的line-height:32px*1.375=44px(normal並非精確的等於1.375)

純數字
就是將normal改成一個想要的準確數字。

1.五、各類BOX

<body>
  <p>這個<em>強調</em> 元素爲行內元素</p>
</body>
body{
  font-size:16px;
  line-height:1.5;
}
p{
  font-size:32px;
  padding:10px;
}

containing box
p就是一個containing box,包含了其餘boxs。

inline box
在段落內,有一系列的inline box,inline box不會讓內容成塊顯示,而是排成一行。「強調」是一種inline box,「這個」,「元素爲行內元素」爲一種匿名inline box。

line box
多個inline box組成line box,多個line box組成containing box。

Content Area
Content Area是圍繞着文字的一種看不見的box,高度取決與font-size

inline box與line-height
font-size:32px,line-height:48px,行間距=48px-32px=16px,半行間距=8px。
半行間距會用在Content Area的頂部和底部。


這裏inline box的高度就是line-height。inline box包着Content Area

可是,當line-height小於font-size。line box的高度仍是line-height,因此line-box的高度小於Content Area的高度,Content Area會溢出line-box。

inline box 與line box
line box的高度取決於他內部最高的inline box。

二、vertical-align

vertical-align是用來對齊內聯級元素的。設置爲如下display屬性的元素,它們都被認爲屬於內聯級元素。inlineinline-block or inline-table (本文中不涉及此種狀況):

inline內聯元素基本上是包裹文本的標籤。

inline-block內聯塊元素則如它們的名字所示:擁有內聯特性的塊元素。他們能夠有width和height(多是由本身的內容定義),以及padding、border和margin。

內聯級元素彼此緊挨着放在一行中。一旦有更多的元素被放置到當前行中,一個新的行將會在它下面建立。全部這些行有所謂的「行框」,行框中包含全部的內容。不一樣大小的內容意味着不一樣高度的行框。在下面的插圖中,行框的頂部和底部都是用紅線表示的。

在行框中,元素的vertical-align屬性是負責垂直對齊的。那麼,到底元素垂直對齊的參照物是什麼?

參照物:父元素的基線和外邊緣
看看元素的基線和行框的外觀:
inline元素

三行並排的文本。行框的頂部和底部邊緣用紅線表示,字體的高度由綠線表示,基線由一條藍線表示。在左邊,有一個line-height設置爲與字體font-size大小相同高度的文本,綠線和紅線重疊在一條線上。在中間,line-height是字體的兩倍大。在右邊,line-height是字體大小的一半大。

內聯元素(display:inline)的外邊緣與其行高的頂部和底部邊緣對齊,行高能夠小於字體的高度。因此,行框就是上面的圖中的紅線。

內聯元素的基線是字符放置的位置線(字母x底部所在的水平線),即圖中的藍線。粗略地說,基線是在字體1/2高度的下面的某個地方。

inline-block元素
inline-block由於已經有寬和高,可能存在多行,每行都有本身的基線和行框,因此會比較特殊。

上圖中,最外層是div,裏面分別是三個inline-block的span,黃色爲border,綠色爲padding,藍色爲content area(一個span,其中有一個字母「C」)。左邊的inline-block的span的內容(span)是一個正常文檔流元素。中間的inline-block的span還額外加了overflow: hidden。右邊的inline-block的span包含一個流外的span(但內容區域有一個高度)(譯者注:流內的元素必須是普通文檔流(normal flow)中的元素,流外的元素必須是浮動或絕對定位的元素以及根元素。)。藍線爲每一個inline-block的span的基線。內聯塊元素的外邊緣是其margin框的頂部和底部邊緣,即圖中的紅線。

內聯塊元素(上圖三個inline-block的span)的基線取決它包含的內容是否在文檔流中:

  • 在流內內容的狀況下,內聯塊元素的基線是正常流中最後一個內容元素的基線(左邊的例子)。對於這最後一個元素,它的基線是根據它本身的規則找到的。
<div class="demo1">
  x<span>
    x<span style="display:inline-block;height:30px;width:100px;background-color:blue">x</span>
    x
  </span>
</div>
.demo1 span{
  display:inline-block;
  background-color:silver;
  height:90px;
  
}


灰色背景的元素內部有三個子元素,兩個「x」,一個span。元素的基線就是最後一個正常流元素(「x」)的基線。
修改元素的長度,使其內容出現多行:

最外面的X怎麼也跟着移動了?這涉及行框基線的移動,下文細說。

  • 在流內內容但內聯塊元素有overflow:hidden屬性的狀況下,基線是內聯塊元素margin框的底部邊緣(例如在中間的圖)。
    修改上面的例子樣式:
.demo1>span{
  display:inline-block;
  background-color:silver;
  height:90px;
  width:100px;
  margin:10px;
  overflow:hidden;
}


經過最外面的x大體知道行框的基線位置,就是內聯塊元素的下外邊距的地方,也是內聯塊元素元素的基線位置。
一開始此處有疑惑:內聯塊元素元素的基線跑到了下外邊距處,那麼元素裏面的內容不該該以這條基線作定位嗎?羣裏問了大佬,內聯塊元素已經設了寬高,可能有多行(即便只有一行),每行有各自的行框,而後又根據規則定位了,跟內聯塊元素的基線已經沒有關係。

  • 在流外內容的狀況下,基線是內聯塊元素margin框的底部邊緣(例如在右邊)。
<div class="demo1">
  x<span>
  <span style="display:inline-block;height:30px;width:100px;background-color:blue;">x</span>
  </span>
</div>
.demo1>span{
  display:inline-block;
  background-color:silver;
  height:90px;
  width:100px;
}

加上浮動

<div class="demo1">
  x<span>
  <span style="display:inline-block;height:30px;width:100px;background-color:blue;float:left">x</span>
  </span>
</div>

行框的基線是可變的
當使用vertical-align時,基線放置在哪裏多是最使人疑惑的部分。它須要知足vertical-align的值和行框的高度等全部條件。基線的位置猶如是方程中的一個自由參數。

行框的基線是看不見的,但你可使它很容易看到。只要在文本行的開頭添加一個字符,像我增長了一個「X」的字母。若是這個字符不以任何方式對齊,它將默認地坐在基線上。

圍繞着行框的基線的部分(綠線),咱們能夠稱其爲文本框。文本框能夠簡單地被認爲是行框內的內聯元素,沒有任何對齊。文本框的高度等於它的父元素的字體大小。所以,文本框只圍住了行框內的無格式文本。因爲這個文本框是綁在基線上的,當基線移動時它將移動。(注:此文本框在W3C規範中稱爲「strut(支柱)」)

vertical-align的值
1)將元素的基線,參照父元素的基線對齊

baseline:元素的基線與父元素的基線對齊。

sub:元素的基線偏移到父元素的基線之下。

sup:元素的基線偏移到父元素的基線之上。

:元素的基線相對於父元素的基線偏移了一個百分比(該百分比是對比元素自身的line-height計算得出)。

:元素的基線相對於父元素的基線偏移了一個絕對長度。

2)將元素的中心點,參照父元素的基線對齊

middle:將元素的頂部和底部之間的中心點,對齊父元素的基線之上x-height的1/2之處(x-height爲字母x的字符高度)。

3)將元素的外邊緣,參照父元素的文本框對齊

text-top:將元素的頂部邊緣,對齊到父元素的文本框的頂部邊緣。

text-bottom:將元素的底部邊緣,對齊到父元素的文本框的底部邊緣。

4)將元素的外邊緣,參照父元素行框的外邊緣對齊

top:元素的頂部邊緣對齊到父元素的頂部邊緣。

bottom:元素的底部邊緣對齊到父元素的底部邊緣。

基線的移動
若是一行中有一個高個的元素佔據了整行的高度,那麼vertical-align對它沒有影響。它的頂部和底部沒有空間讓它移動。爲了知足行框基線的對齊方式,行框的基線必須移動。矮個元素設置了vertical-align: baseline。在左邊,高個元素設置了vertical-align: text-bottom。在右邊,高個元素設置了vertical-align: text-top。你能夠看到右邊的基線跳起來了。

(左)將兩個元素放在一行中並設置vertical-align ,它們會使得行框的基線移動到符合它倆的對齊規則之處,而後行框的高度也會隨之調整。(中)添加第三個元素,不超越行框的邊緣,既不影響行框的高度,也不影響基線的位置。(右)添加第三個元素,若是它超出了行框的邊緣,行框的高度和基線調整。在這種狀況下,咱們的前兩個元素也會跟着發生變化。

內聯級元素底部的小間隙

列表項坐在基線上。下面的一點空間,是文本的基線如下預留的depth(在W3C規範中,一個字體的基線以上稱爲characteristic height,基線如下稱爲depth)。想要去掉這個depth空隙,有解決的辦法嗎?只要移動基線的位置就能夠,例如經過設置列表項目vertical-align: middle

水平垂直居中

<div class="box">
        <div class="content">
          自適應垂直居中
        </div>
</div>
html{
  height:100%;
}
body{   
   height: 100%;  
   width: 100%;  
}
.box{
   display:inline-block;
   text-align: center;
   width:50%;
   height:50%;
   background-color:#e1e3cd;
   overflow:hidden;
}
.box:after{
    content:"";
    display:inline-block;
    height:100%;
    vertical-align:middle;
}
.content{
    vertical-align:middle;
    background-color:silver;
    display: inline-block;
    width: 50%;
    height:50%;
}

要將content水平垂直居中定位在box裏,利用vertical-align是其中一種方法。原理是:vertical-align:middle(將元素的頂部和底部之間的中心點,對齊父元素的基線之上x-height的1/2之處(x-height爲字母x的字符高度)。),content確定是要垂直居中的,那隻能修改行框的基線位置(注意:不是修改box的基線,box具備寬高,它裏面的內容可能會有多行,每行有各自的行框,box的基線已經不會影響內容的佈局,可是box的基線仍是會受裏面內容的影響(內聯塊元素的基線是正常流中最後一個內容元素的基線)),使其位於box的垂直中心位置。修改行框的基線,只要在box內加一個高度爲100%的空元素,而後設置vertical-align:middle,添加的元素已經佔滿整個行框高度,而只要移動行框的基線,就能夠知足定位規則,因此行框的基線就被移動到box垂直中心位置。content再按規則對齊到行框基線上就能夠了。

相關文章
相關標籤/搜索