今天在一篇文章中无心看到一个利用伪元素实现垂直居中的方法,费了好大劲理解了它的原理,因而就有了这篇文章。浏览器
这个方法是经过在父元素上添加一个高度 100%、vertical-align: middle
的伪元素实现垂直居中的,效果和代码以下:post
<div class="parent">
<div class="child">child</div>
</div>
复制代码
.parent {
width: 300px;
height: 300px;
border: 1px solid red;
text-align: center;
}
.child {
background: blue;
width: 100px;
height: 40px;
display: inline-block;
vertical-align: middle;
}
.parent::before {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
}
复制代码
在深刻了解以前,先来了解一些基本概念。spa
一行 inline
元素中,取行高最高元素的做为基准元素。.net
咱们都知道,默认状况下,行内元素的垂直对齐方式为基线对齐。这里的基线(base line)指的是英文字母“x”的下端沿: 3d
图片来源:https://blog.csdn.net/lulujiajiawenwen/article/details/8245201code
举个例子,下图的两个行内元素都是基线对齐的,红色的线就是它们的基线: cdn
<div class="parent">
<div class="child1">abcxyz</div>
<div class="child2">efghij</div>
</div>
复制代码
.parent {
width: 300px;
height: 100px;
border: 1px solid blue;
}
.child1 {
display: inline-block;
height: 20px;
background-color: green;
}
.child2 {
display: inline-block;
height: 20px;
background-color: yellow;
}
复制代码
行内元素是如何判断垂直对齐的位置呢?是依据 vertical-align
属性。按照 w3school 上的解释:该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐方式,默认值为 baseline。blog
再看一遍 vertical-align
的概念:该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐方式。这里有两个词组:什么是“行内元素的基线”?什么是“该元素所在行的基线”?图片
毫无疑问,“行内元素的基线”就是咱们在基线中所说的:字母“x”的下端沿。咱们在一个元素里写一个"x",它的下沿就是这个元素的基线。get
能够看到,元素的基线和元素的底线之间是有间距的(上图"x"和红色底边之间),这部分留给"g"、"j"等字母或中文字符
那么什么是“该元素所在行的基线”?一句话归纳就是:所在行的基准元素在对齐时所依据的那条线。咱们把该元素所在行看成父元素,这句话代表,父元素的基线是由它的一个子元素——基准元素决定的,基准元素依据哪条线对齐,父元素的基线就是哪条线。
这时咱们就明白了这两个“基线”的区别:
也就是说:若是基准元素采用中线对齐,那么所在行的基线就是基准元素的中线;若是基准元素采用顶线对齐,那么所在行的基线就是基准元素的顶线。
有了上面的铺垫,咱们再回过头来看一下这句话:默认状况下,行内元素的垂直对齐方式为基线对齐。那么,如何根据这句话解释下面的两个元素在垂直方向上的对齐过程呢?
.parent {
width: 300px;
height: 100px;
border: 1px solid blue;
}
.child1 {
display: inline-block;
width: 50px;
height: 100%;
background-color: green;
}
.child2 {
display: inline-block;
width: 50px;
height: 20px;
background-color: yellow;
}
复制代码
可能有人会说,这很简单啊,两个元素都没有设置 vertical-align
属性,那么按照默认状况,它们都是基线对齐,因此内部文字就都沿着红线对齐了。
这句话错在哪儿?错在“都是”。正确过程应该是:基准元素按照本身的基线对齐,其他行内元素按照父元素的基线对齐:
child1
child1
的 vertical-align
属性默认值为 baseline
,所以它对齐本身的基线 —— 做为基准元素,位置并无发生变化,可是会影响父元素的基线位置child1
的基线child2
的 vertical-align
属性默认值为 baseline
,所以它的垂直对齐方式也是“基线对齐”child2
是按照父元素的基线对齐,而不是按照本身的基线对齐,即 child2
的基线对齐父元素的基线彷佛看起来两种解释最后都没啥区别啊?为何必定要这么大费周章地讲一遍对齐过程呢?如今让咱们给 child1
添加 vertical-align: middle
,想想,child2
的位置在哪儿呢?
咦?给 child1
添加 vertical-align: middle
,child2
就自动“垂直居中”了?!但是我没有给 child2
设置 vertical-align: middle
啊,这是为何?
按照咱们以前的过程再分析一遍,就简单多了:
child1
child1
此次采用 vertical-align: middle
中线对齐 —— 做为基准元素,位置并无发生变化,可是会影响父元素的基线位置child1
的中线child2
的 vertical-align
属性默认值为 baseline
,所以它的垂直对齐方式也是“基线对齐”child2
按照父元素的基线对齐,因此就是它的基线要对齐 child1
的中线那这里咱们又要思考,child2
真的垂直居中了吗?答案是没有。由于咱们说“ child2
的基线对齐的是 child1
的中线”,因此 child2
并无垂直居中,而是在中部靠上一点点的位置。
如今咱们给 child2
添加 vertical-align: middle
,会发现它降低了一点点,这时候它就真正的垂直居中了:
咱们再分析一下这个过程:
child1
的中线child2
的 vertical-align
属性为 middle
,采用中线对齐,因此就是它的中线对齐父元素的基线,又或者,至关于它的中线对齐 child1
的中线到这时,相信你对于浏览器如何实现垂直对齐,已经有一个较为深刻的理解了。你能够修改 child1
与 child2
的 vertical-align
属性为其余值(sup
、top
、...),看看会发生什么,并试着用以上过程解释一下缘由。
vertical-align
属性对应的线vertical-align
属性对应的线对齐到父元素的基线首先,before
伪元素渲染在父元素的全部子元素以前,after
伪元素插入在父元素的全部子元素以后。也就是说伪元素和子元素是同级的。
回到咱们文章开头所说的案例,原理呼之欲出:利用content: ''; height: 100%
获得一个宽度为 0 的伪元素,即它不会显示出来;高度 100%,因此它最高,是所在行的基准元素;利用 vertical-align: middle
将父元素的基线设置为伪元素的中线,而后其余行内元素采用中线对齐时,天然就是要对齐伪元素的中线了。而伪元素的高度为 100%,因此它的中线就是整个父元素的中线,这就实现了其余行内元素的垂直居中。
从编译原理的角度出发,我这样理解上面的过程:
浏览器在解析 CSS 的时候,对于一个行内元素:
vertical-align
属性是一个固有属性vertical-align
属性对应的线做为本身的基线而后把全部的行内元素,依据 vertical-align
属性,对齐到父元素的基线上。
这也解释了为何设置基准元素的
vertical-align
属性时,基准元素位置不变,由于父元素的基线原本就是根据它的vertical-align
属性值取的
以上就是我对 vertical-align
和基线的理解,欢迎各位大佬批评指正。