1. 程式人生 > >關於多元素垂直居中

關於多元素垂直居中

特性 uri 註意 相對 啊啊啊 text tab 解釋 內聯

關於多元素垂直居中

一、場景描述

  • 一個高度固定的div,做為父元素。
  • 數個高度隨機的div,做為子元素,需要在父元素內被垂直居中。

二、相關概念回顧

1.幾種box

  • inline box:display為inline或inline-block的元素會形成inline box;行內文本會形成inline box;
  • line box:一行內所有的inline boxes會構成line box。其中inline box中高度最高的那個的高度便是line box的高度。

2.幾種line

  • baseline(基線)
  • ascendar height(上沿)
  • descender height(下沿)
  • x-height

技術分享圖片

另外還有line-height:對於塊級元素,它指定元素行盒(line box)的最小高度。對於非替代的inline元素,它用於計算行盒(line box)的高度。它是繼承屬性

更多解釋參見深入理解 CSS:字體度量、line-height 和 vertical-align

3. css屬性 vertical-align

參考MDN文檔可知:

CSS 的屬性 vertical-align 用來指定行內元素(inline)或表格單元格(table-cell)元素的垂直對齊方式。

使用場景

mdn文檔上是這樣描述的:

  1. to vertically align an inline element‘s box inside its containing line box. For example, it could be used to vertically align an 技術分享圖片 in a line of text.(設置一個inline元素的box相對於 包含它的line box
    在垂直方向上的位置)
  2. to vertically align the content of a cell in a table(設置一個table中的一個cell的內容在垂直方向上的位置)

相關特性

  • 初始值:baseline
  • 適用元素:
  • inline-level 元素
  • table-cell 元素.
  • ::first-letter and ::first-line.
  • 是否是繼承屬性 否
  • Percentages: refer to the line-height of the element itself(相對於該元素自己的line-height)

補充知識點:

::first-letter 會選中某 block-level element(塊級元素)第一行的第一個字母,並且文字所處的行之前沒有其他內容(如圖片和內聯的表格)

::first-line ::first-line CSS pseudo-element (CSS偽元素)在某 block-level element (塊級元素)的第一行應用樣式。

可能值

  • baseline:Aligns the baseline of the element with the baseline of its parent.將該元素的baseline對準它父元素的baseline
  • middle:Aligns the middle of the element with the baseline plus half the x-height of the parent.將該元素的baseline對準父元素的baseline + 1/2的x-heihgts

註意: 這些值雖然是相對於父元素而言的,但相對的僅僅是父元素中的一個line box。

三、實踐

1.Step1

代碼

html:

  <body>
    <div class="parent">
      <div class="child1">
        我是一號div 哈哈哈哈哈<br>哈哈哈哈哈哈
      </div>
      <div class="child2">
        我是二號div
      </div>
    </div>
  </body>

css:

.parent {
  height:300px;
  background-color: blue;
}

.child1 {
  background-color: red;
  display: inline-block;
}
.child2 {
  background-color: yellow;
  display: inline-block;
}

結果:

技術分享圖片

發現:

  1. 默認情況下,兩個為inline-block的子元素的vertical-align為baseline。
  2. 兩個inline-block的子元素的baseline在一條線上
  3. 兩個inline-block形成的兩個inline box組成的line box的高度是最高的的那個inline-box的高度,即一號div的高度
  4. vertical-align是相對於包含這些inline box的line box的位置的,而line box的高度、baseline、middle line的位置都是由最高的那個inline box決定的。
  5. 一號div也是由若幹個line box構成(一行字就是一個line box)。一號div的baseline就是最後一個(最下面一個)的line box的baseline。那麽二號的baseline是它的line box的baseline, 和一號div的baseline重合。同時它倆形成的line box的baseline也和它們各自的baseline都重合。

2.Step2

為了驗證上述3.可以將html修改一下(css不變)

代碼

  <body>
    <div class="parent">
      <div class="child2">
        二號div
      </div>
      <div class="child1">
        一號div,啊啊啊啊啊啊啊啊啊啊<br>啊啊啊啊啊啊啊啊
      </div>
    </div>
  </body>

css:同上

結果:

技術分享圖片

發現:

上述結論3.是對的,且可以得到:

  1. 所有inline box的baseline的位置是由最高的那個inline box的baseline的位置決定的。

3.Step3

我們知道vertical-align是相對於包含這些inline box的line box的位置的,而line box的高度、baseline的位置都是由最高的那個inline box決定的。那麽真正的父元素,display為block的這個元素,有沒有baseline呢?答案是否定的。在inline-block元素處於block元素內部的情況下,它們兩個vertical-align決定的對齊策略針對的是同級的inline-block;也就是說它們的vertical-align造成的結果是它們自己的相互對齊,與父元素無關。

故現在試驗一下把父元素變為inline-block的結果。

代碼

html:同step1中的html代碼。

css:

.parent {
  height:300px;
  background-color: blue;
  display: inline-block;
  line-height: 300px;
}

.child1 {
  background-color: red;
  display: inline-block;
}
.child2 {
  background-color: yellow;
  display: inline-block;
}

結果:

技術分享圖片

此時父元素是inline-block且line-height為300px。由於line-height是繼承的,所以兩個子元素的line-height也是300px。

另外,由於父元素變成了inline-block,所以其寬度不再自動是body的100%,其寬度變成了由內容決定。(這又涉及到另一個問題:父子元素尺寸繼承規律 參見我的另一篇博客)

發現:

  1. 當父元素是block時,vertical-align只與同級元素有關,和父元素無關——只和它們自己形成的一個line box有關。
  2. 當父元素是inline-box時,vertical-align和父元素的line-height相關。

4.Step4

實現垂直居中。

既然這些inline-block只和同級元素有關,那麽就創建一個高度等於父元素的同級inline-block。然後由於這個高度等於父元素的同級元素是這些inline-block中最高的,故由這些inline box組成的line box的baseline、x-height的位置都由該高度等於父元素的inline-block決定。

代碼

html:同step1中的html代碼。

css:

.parent {
  height:300px;
  background-color: blue;
}
.parent::before {
  display: inline-block;
  height: 100%;
  content: ‘‘;
  vertical-align: middle;
}
.child1 {
  background-color: red;
  display: inline-block;
  vertical-align: middle;
}
.child2 {
  background-color: yellow;
  display: inline-block;
  vertical-align: middle;
}

結果

技術分享圖片

5.Step5

為了更深入地也就vertical-align,現在在Step4的基礎上,將幾個inline-block的vertical-align分別進行修改。

代碼

html:同step1中的html代碼。

css:

.parent {
  height:300px;
  background-color: blue;
}
.parent::before {
  display: inline-block;
  height: 100%;
  content: ‘‘;
  vertical-align: middle;
}
.child1 {
  background-color: red;
  display: inline-block;
}
.child2 {
  background-color: yellow;
  display: inline-block;
  vertical-align: middle;
}

結果

技術分享圖片

給上述child1增加屬性:vertical-align:top 結果如下:

技術分享圖片

發現

  1. 每個inline-block都要自己設置vertical-align來決定自己的位置,否則自己的位置就在baseline上。
  2. 必須設置基準inline-block的vertical-align為middle。

參考資料

http://zxc0328.github.io/2015/07/23/vertical-align-middle/
https://zhuanlan.zhihu.com/p/25808995
https://developer.mozilla.org/zh-CN/docs/Web/CSS/vertical-align

關於多元素垂直居中