关于多元素垂直居中

一、场景描述

  • 一个高度固定的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

503055-20180623185017580-1472259884.jpg

另外还有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;
}
结果:

503055-20180623185055020-2127324612.png

发现:
  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:同上

结果:

503055-20180623185117425-2067558537.png

发现:

上述结论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;
}
结果:

503055-20180623185311893-1348995339.png

此时父元素是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;
}
结果

503055-20180623185337620-1237935716.png

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;
}
结果

503055-20180623185428863-759689778.png

给上述child1增加属性:vertical-align:top 结果如下:

503055-20180623185443127-103023588.png

发现
  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

转载于:https://www.cnblogs.com/Bonnie3449/p/9218393.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值