vertical-align和line-heigh搞基那些事兒

文章首發於個人博客tc9011's notescss

原由

項目中在應用Angular/Material的card組件的時候遇到以下問題:html

它的代碼大概是這樣的:wordpress

<ul>
  <li>
    <md-card>
      <img md-card-image src="X.png" alt="img">
      <md-card-title>湯誠湯誠湯誠湯誠</md-card-title>
      <md-card-subtitle>湯誠湯誠湯誠湯誠</md-card-subtitle>
      <button>查看詳情</button>
    </md-card>
  </li>
  <li>
    <md-card>
      <img md-card-image src="X.png" alt="img">
      <md-card-title>湯誠湯誠湯誠湯誠</md-card-title>
      <md-card-subtitle>湯誠湯誠湯誠湯誠</md-card-subtitle>
      <button>查看詳情</button>
    </md-card>
  </li>
  <li>
    <md-card>
      <img md-card-image src="X.png" alt="img">
      <md-card-title>湯誠湯誠湯誠湯誠</md-card-title>
      <md-card-subtitle>湯誠湯誠湯誠湯誠</md-card-subtitle>
      <button>查看詳情</button>
    </md-card>
  </li>
  <li>
    <md-card>
      <img md-card-image src="X.png" alt="img">
      <md-card-title>湯誠湯誠湯誠湯誠</md-card-title>
      <md-card-subtitle>湯誠湯誠湯誠湯誠湯誠湯誠湯誠湯誠湯誠湯誠湯誠湯誠</md-card-subtitle>
      <button>查看詳情</button>
    </md-card>
  </li>
  <li>
    <md-card>
      <img md-card-image src="X.png" alt="img">
      <md-card-title>湯誠湯誠湯誠湯誠</md-card-title>
      <md-card-subtitle>湯誠湯誠湯誠湯誠</md-card-subtitle>
      <button>查看詳情</button>
    </md-card>
  </li>
</ul>複製代碼
ul{
  width: 1200px;
  margin: 0 auto;
  margin-top: 40px;
}

li{
  display: inline-block;
  margin-right: 70px;
  margin-bottom: 60px;
  &:nth-child(3n){
    margin-right: 0;
  }
}複製代碼

我一開始覺得是li標籤之間空隙致使的,因而就按照常規方法,把font-size設置爲0,but,最後一個元素好像很執拗,一動不動,這就讓我很尷尬。佈局

緣由

參考張鑫旭的CSS深刻理解vertical-align和line-height的基友關係spa

vertical-align默認值是baseline, 也就是基線對齊。而基線是什麼,基線就是字母X的下邊緣(參見「字母’x’在CSS世界中的角色和故事」一文)。而文字高度是由line-height決定的。卡片上面留白行爲表現,本質上,就是vertical-alignline-height背地裏搞基形成的。這裏借用一下張鑫旭文章中的圖片可能更好理解一點:.net

在這裏li元素display:inline-block,而在CSS2的可視化格式模型文檔中,一個inline-block元素,若是裏面沒有inline內聯元素,或者overflow不是visible,則該元素的基線就是其margin底邊緣,不然,其基線就是元素裏面最後一行內聯元素的基線。3d

能夠從下圖看出,在li的基線是最後一行文字的基線(查看詳情按鈕不計入,由於已經脫離文檔流了)。而倒數第二個li的文字折行了,最後一個li文字只有一行,可是最後一個li元素要像它的好基友看齊,因而它把本身變矮了(和基友是真愛)。此時也能夠說明爲何font-size設置爲0,由於我給那段文字手動設置了font-size,按照優先級來講,lifont-size固然不起做用。code

知道緣由後,咱們能夠試下把liline-height設置爲0,獲得下面的效果:cdn

此時圖片下面那兩行字的行高就會受到影響,兩行文字會疊在一塊兒,這樣我須要手動爲文字加一個line-height,可是對於我這樣的懶人來講,太麻煩了。htm

此時還有一種方法就是修改vertical-align的值,讓li元素的vertical-align變成top/bottom/middle。這時候一樣會獲得下圖的效果,可是卡片裏面的文字卻仍是正常顯示,恩,簡直完美。

vertical-aligntop/bottom/middle這三個值究竟是啥東西咧,能夠看MDN上vertical-align的解釋,並結合張鑫旭那篇文章給出的圖理解:

  • middle:元素中線與父元素的小寫x中線對齊。

  • top:元素及其後代的頂端與整行的頂端對齊。

  • bottom:元素及其後代的底端與整行的底端對齊。

還有一篇老外的文章寫得也蠻好的Deep dive CSS: font metrics, line-height and vertical-align

相似問題的解決方案

  • 將圖片轉換爲塊級對象

圖片默認是inline水平的,而vertical-align對塊狀水平的元素無感。所以,咱們只要讓圖片display水平爲block就能夠了,咱們能夠直接設置display或者浮動、絕對定位等(若是佈局容許)。

img { display: block }複製代碼
  • 使用其餘vertical-align值

比方說bottom/middle/top都是能夠的。

  • 直接修改line-height值

只要行高足夠小,實際文字佔據的高度的底部就會在x的上面,下面沒有了高度區域支撐,天然,圖片就會有容器底邊貼合在一塊兒了。

  • line-height爲相對單位,font-size間接控制

若是line-height是相對單位,例如line-height:1.6或者line-height:160%之類,也能夠使用font-size間接控制,比方說來個狠的,font-size設爲0, 本質上仍是改變line-height值。

參考文章

  1. CSS深刻理解vertical-align和line-height的基友關係
  2. vertical-align
  3. li和img標籤之間空隙解決辦法
  4. Deep dive CSS: font metrics, line-height and vertical-align
相關文章
相關標籤/搜索