css属性 vertical-align 
vertical-align作用 
指定元素的垂直对齐方式,只对行内元素有效,就是display的属性为inline、inline-block、inline-table,再加一个table-cell (<td></td>)的元素,
行内元素的几条线和行高 

图片来自:https://www.zhangxinxu.com/wordpress/2015/06/about-letter-x-of-css/
上行线 
图中的ascent
上行线和盒子最上边的一小块高度是上行线高度ascender height
下行线 
图中的descent
下行线和盒子最下边的一小块高度是下行线高度descender height
基线 
图中红色的线baseline,也就是字符X的最下边
中线 
图中的 median,也就是x的底部,再往上多一个x-height高度后的那条线。
大意就是:middle指的是基线往上1/2 "x-height"高度。可以近似脑补成字母x交叉点那个位置。
由此可见,vertical-align: middle并不是绝对的垂直居中对齐,我们平常看到的middle效果只是一种近似的效果。原因很简单,因为不同的字体,其在行内盒子中的位置是不一样的,比方说’微软雅黑’就是一个字符下沉比较明显的字体,所有字符的位置相比其他字体要偏下一点。要是vertical-align: middle是相对容器中分线对齐,你会发现图标和文字不在一条线上,而相对于字符x的中心位置对齐,我们肉眼看上去就好像和文字居中对齐了。
行高 line-height 
最多的说法是两行字符基线与基线之间的距离,其实也是中线与中线之间的距离,也是上行线与上行线之间的距离,想怎么说就怎么说,高度都是一样的
所以我这样理解:行高是 上行线高度+上行线到下行线之间的高度 +下行线高度
所以,当一个盒子的height=line-height时,文字就会垂直居中显示了
当行高小于height时,文字就偏上显示,(因为行高不够所以偏上显示)
当行高大于height时,文字就偏下显示,(因为行高冒了,所以文字就偏下显示)
vertical-align属性值 
操作表格单元格 
如果是操作单元格td,表格单元格的值
top:使单元格内边距的上边缘与该行顶部对齐。(就是盒子模型的content的上边缘)
middle:使单元格内边距盒模型在该行内居中对齐。(就是盒子模型的content的中间)
bottom:使单元格内边距的下边缘与该行底部对齐。(就是盒子模型的content的底部)
行内元素值 
tip 没有基线的元素,使用外边距的下边缘替代。
baseline 
使元素的基线与父元素的基线对齐。
sub 
使元素的基线与父元素的下标基线对齐。
super 
使元素的基线与父元素的上标基线对齐。
text-top 
使元素的顶部与父元素的字体顶部对齐。
text-bottom 
使元素的底部与父元素的字体底部对齐。
middle
使元素的中部与父元素的基线加上父元素x-height(译注:x高度)的一半对齐。
length 
使元素的基线对齐到父元素的基线之上的给定长度。可以是负数。
1、正值:基线向上移动
2、负值:基线向下移动
percentage 
使元素的基线对齐到父元素的基线之上的给定百分比,该百分比是line-height属性的百分比。可以是负数。
1、正值:基线向上移动
2、负值:基线向下移动
例子理解 
辨别“行内元素的基线”与“行内元素所在行的基线” 
1、行内元素的基线:就是字母x的下边沿,就是上面讲的红色的线 baseline,元素的基线和下行线之间还留有一定的距离,这些距离是留给那些带尾巴的字母或者是汉字的空间,比如j,y,g等等
2、元素所在行的基线:就是所在行的基准元素,对齐时所依据的那条线。把基准元素所在行当作父元素,也就是说,所在行的基线由他的一个子元素--基准元素所决定。
如果基准元素采用中线对齐,那么所在行的基线就是基准元素的中线,如果基准元素采用顶线对齐,那么所在行的基线就是基准元素的顶线。
所以,基准元素依据哪条线对齐,父元素的基线就是哪条。
另外,根据有无vertical-align属性,还可以分为下面三种情况
(1)全部都没有添加vertical-align时,默认以基准元素的基线对齐。
(2)基准元素添加vertical-align,同一行的其他inline box 没有添加,这时,就是上面说的情况,如果基准元素采用中线对齐,那么所在行的基线就是基准元素的中线,如果基准元素采用顶线对齐,那么所在行的基线就是基准元素的顶线。
(3)当基准元素没有添加vertical-align,同一行的其他inline box添加了,这时添加vertical-align属性的inline box 以基准元素的默认的线对齐,代入例子就是,如果其他元素对齐方式改为vertical-align: top,那就对齐基准元素的top线,如果时bottom,就对齐bottom线,以此类推
(4)基准元素和同一行的其他inline box都添加了vertical-align属性,这其实和第三种情况一样,基准元素因为是最高的那一个,无论怎么对齐,都是一样,位置不变,把整一行撑满了,其他元素就以基准元素的线去对齐,该对中线就对中线,该对上线就对上线,以此类推
基准元素 
同一行中最高的那个inline box就是这一行的基准元素。
如果这个inline-box没有文字,则没有基线,默认基线位置为下外边距的边缘处,没有外边距时就是元素的最下边。
如果有文字,基线就是上面提到的红色线baseline,也即字母x的最下边。
父元素基线计算方式 
默认情况下,行内元素的垂直对齐方式都是以基线对齐
没有文字时,如下图所示
- 黄色和绿色都是inline box,默认以这一行的基线对齐
 - 这一行的基线就是黄色的基线(因为它在这一行最高,也即是这一行的基准元素)
 - 黄色因为没有文字,默认没有基线,所以以它的下边距的边缘处为基线
 - 所以绿色框就以黄色块(也即这一行的基准元素)的基线对齐,绿色块本身默认以基线对齐,由于它也是没有文字的inline box,所以默认基线也是它的下边距的最外边缘处。最终就成了如下的布局样式。
 
注意,inline-block元素间有空格或是换行会产生间隙,使用
font-size: 0;可去除

<style>
    .father {
        width: 300px;
        border: 1px solid green;
        font-size: 0;
    }
    .son1 {
        display: inline-block;
        width: 50px;
        height: 100px;
        background-color: yellow;
        margin-bottom: 10px;
    }
    .son2 {
        display: inline-block;
        width: 50px;
        height: 20px;
        background-color: blue;
    }
</style>
<body>
    <div class="father">
        <div class="son1"></div>
        <div class="son2"></div>
    </div>
</body>
<style>
    .son1 {
        display: inline-block;
        width: 50px;
        height: 100px;
        background-color: yellow;
        margin-bottom: 10px;
    }
</style>- 有文字时,如下图所示 
- 黄色和绿色都是inline box,默认以这一行的基线对齐
 - 这一行的基线就是黄色的基线(因为它在这一行最高,也即是这一行的基准元素)
 - 黄色有文字,默认基线为上面说到的字母
x的最下边,所以本行的基线就是Son1的基线 - 所以绿色框就以黄色块(这一行的基准元素)的基线对齐,默认以基线对齐,因为绿色框也是有文字的,所以默认基线也是文字的基线。最终就成了如下的布局样式。
 
 

<style>
    .father {
        width: 300px;
        border: 1px solid green;
        color: red;
    }
    .son1 {
        display: inline-block;
        width: 80px;
        height: 100px;
        background-color: yellow;
    }
    .son2 {
        display: inline-block;
        width: 80px;
        height: 20px;
        background-color: blue;
    }
</style>
<body>
    <div class="father">
        <div class="son1">Son1</div>
        <div class="son2">Son2</div>
    </div>
</body>3、使用vertical-align实现son2垂直居中
先来看一个效果,如下图,只是在son1增加了一个vertical-align: middle;,但是son2却跑到了中间,这是为什么呢?
我们还按照上面一步步分析一下:
- son1和son2都是inline box,默认以这一行的基线对齐
 - 这一行的基准元素是黄色块(因为它最高),黄色块有文字,所以基线就是文字的基线,默认以基线对齐
 - 但是主动修改了son1(基准元素)的对齐方式
vertical-align:middle,所以整行的对齐方式就变为了以son1(基准元素)的中线对齐。 - 所以son2的基线就对齐了son1(所在行的基准元素)的中线,就形成了下面的效果。
 
实际上,son2并没有完全在中间显示,有点偏上,因为son2的基线就是文字的基线,偏下一点,所以要想实现完全居中的效果,可以在son2上也加一个vertical-align: middle

实战:使用伪元素和vertical-align: middle实现垂直居中 
<style>
    * {
        margin: 0;
    }
    .parent {
        width: 300px;
        height: 300px;
        border: 1px solid red;
        text-align: center;
    }
    .child {
        background: blue;
        width: 100px;
        height: 40px;
        line-height: 40px;
        color: #fff;
        display: inline-block;
        vertical-align: middle;
    }
    .parent::before {
        content: '';
        height: 100%;
        display: inline-block;
        vertical-align: middle;
    }
</style>
<body>
    <div class="parent">
        <div class="child">child</div>
    </div>
</body>分析居中的原理:
- 在parent增加了一个after伪元素,相当于这个伪元素和child变为了兄弟关系
 - 伪元素after设置为inline-block,高度设置为父元素的高度,child也设置为了inline-block
 - 这时伪元素after和child就变为了处于同一行的inline box
 - 默认以基准元素(也即伪元素after,因为它比较高)的基线对齐
 - 因为伪元素设置了
vertical-align: middle属性,所以整行就以伪元素的中线对齐 - child因为有字,默认基线就是正常行内元素的基线,因为基线偏下,所以也给child增加一个
verticle-align: middle - 让child的中线和基准元素的中线对齐,最终就实现了垂直居中的效果
 
参考:
https://www.jianshu.com/p/ce7e4a997a2c
https://www.jianshu.com/p/59f31a1704de
https://juejin.cn/post/6844903621327323143#comment
https://developer.mozilla.org/zh-CN/docs/Web/CSS/vertical-align
https://www.zhangxinxu.com/wordpress/2015/06/about-letter-x-of-css/