参考文章:
Vertical-Align: All You Need To Kno 张鑫旭:字母'x'在 CSS 世界中的角色和故事 张鑫旭:我对 CSS vertical-align 的一些理解与认识 张鑫旭:CSS 深入理解 vertical-align 和 line-height 的基友关系
一 概览
本文从微观层面讲述 vertical-align 的工作原理,工作环境.并整理了用 vertical-align 实现文本和图片居中的方法.
二 涉及内容概念
1. 顶线,中线,基线,底线
分别对应英文作业本的四条线:
图 1 - 四条线
基线最为重要,行内元素就躺在这条线上.且行内元素默认基线和父元素(行框)基线对齐.
中线的定义为:中线位于基线的上方,与基线的距离为小写字母 x 高度的一半(即 0.5ex),而 ex 同 font-size 相关,大部分浏览器认为 1ex = 0.5em(em 同样也是相对单位,不是绝对单位),因此会将基线以上 1/4em 处作为中线来对齐.
2. 内容区
顶线和底线包裹的区域.
内容区由字体大小和字数决定,跟行高半毛钱关系没有.
给一个没有设置行高的行内元素设置背景,可以看到其内容区:
图 2 - 内容区
3. 行高
简单讲就是行内元素所占的高度.
学术点就是内容区加上以内容区为中心上下对称扩展的空白区域,也就是上下行基线之间的距离.
4. 行距(行间距)
上一行的底线和下一行的顶线之间的距离.
也就是:(上一行行高 - 内容区高度)/2+(下一行行高 - 内容区高度)/2
5. 行内框(inline-box)
用例子来说明:
<p class="two-p">
<span class="two-span span1">我有自己的行内框</span>
<span class="two-span span2">我也有自己的行内框</span>
<span class="two-span span3">我也有自己的行内框</span>
</p>
图 3 - 行内框和行框
虽然三段话在同一行内,但是它们各有各的一块 "区域" -- 一个长方体,将他们各自包裹起来,这些长方体在行内不一定对齐.
这些长方体就是行内框.
每个行内元素有自己的行内框.
文本行内框高度 = 行高 = 内容区 + 行距
图片行内框 = 内容区 + padding+border+margin (也就是它自己的盒子模型)
图 4 - 没有加内外边距的图片的行内框
.img {
margin: 10px;
padding: 10px;
}
图 5 - 加上内外边距之后图片的行内框
6. 行框(line-box)
图 3 中的行框就是灰色背景的那块区域.
可见,行框的任务就是包裹同一行行中的行内框,方便页面的渲染.
可以想象成一个大的快递箱,这个快递箱把很多大小不一的小快递箱包裹起来.那么这些大快递箱可以很整齐地摆放,而不是一对小快递箱随意堆在一起.
行框的高度由行内框最高点和最低点决定.
图 4 - 行内框和行框
7. 包含框
一个个行框组成了包含框.
三 vertical-align 的值
top:元素顶部(行内框)和行框顶部对齐
bottom:元素底部和行框底部对齐
baseline:默认值,元素基线和行框(父元素)基线对齐
sub:下标
super:上标
text-top:元素顶部和行框(父元素)文本(不是图片或其他)的顶部对齐, 这里的文本指的是行框中没有添加任何样式的文本(自己实验得出,如有误请指正)
text-bottom:元素底部和父元素文本的底部对齐,这里文本同上
middle:元素的中垂点和父元素的基线向上半个 "x" 距离的那根线对齐,垂直居中的中流砥柱
<length>:具体高度,比如 10px
<percentage>:百分比,相对基线偏移行高的百分比.比如,行高 100px,偏移 10%,即相对基线向上偏移 10px
四 行框的基线怎么确定
1. 主要知识点:
行内元素基线对齐是和父元素也就是行框的基线对齐.
行框的基线会为了满足布局,行高最小化等需求而改变位置.
可以通过匿名行内元素 "x" 来确定父元素基线位置.
2. 详细内容:
正如每个行内元素自己的基线,行框也有自己的基线.
行框的基线由所有行内元素的基线来确定.
行框的基线位置不是固定不变的,是会改变的.
行框需要其基线来满足一些需求,比如,垂直对齐,使行高最小化等等.当它遇到这些需求的时候,就会调整基线的位置.
举个例子,现在有三个行内元素:
<div class="one">
<span class="icon taller"></span>
<span class="icon shorter"></span>
xxx
</div>
图 5 - 行框的基线
行框的基线相对于匿名行内元素 "x" 的最低点是不对的,它永远和 "x" 元素的最底点对齐.
现在,给长条的绿色长方形加上一个样式:
vertical-align:middle
:
图 7 - 长条形垂直居中后行框的基线
讲道理,我们设置了长条形的样式,应该是长条形下移而不是另外两个行内元素上升呀.
如果从微观来看,长条形撑起了行框的高度.行框内已经没有任何空间给它移动了.可以理解为行高总是尽可能的小.
上面也说过,行框的基线会为了满足一些需求而移动.
所以行框就把基线往上移,移到长条形的中垂线再向上 1/2 个 "x" 的距离.(1/2"x" 的距离下面会讲到)这样子行高就不会增大.
如果长条形不变,短条形设置
vertical-align:middle
:
图 8 - 短条形垂直居中后行框的基线
移动的就是短条形而不是其他两个行内元素了.因为这样做行高的增加是最小的.
所以为什么有时候想要让某一个元素行内居中,改变的是其他行内元素的位置呢?有答案了.
五 莫名的空隙
1. inline-block 元素底部的空隙
比如,在一个 div 中放入一张图片,会发现图片的底部和 div 的底部不是贴合的,有一个空隙:
图 9 - 图片底部有空隙
同样地,写网页导航的时候,设置每个 li 的样式为
display:inline-block
,这时候会发现,导航的下面也有一条空隙:
图 10 - 导航条底部也有空隙
这条空隙其实是行内元素基线和底线之间的空隙.
想要去掉这条空隙,要么把基线移走,要么直接让它消失.
比如,元素设置样式:display:block:变成非行内元素,基线就不复存在了:
图 11 - 图片设置为块元素
又比如,元素设置样式:
vertical-align:middle/text-top/text-bottom/bottom
,将父元素的基线往上移:
图 12 - 设置元素的 vertical-align 为 middle
再比如,在元素内写入文本,让父元素的基线上移:
图 13 - 元素内写入文本让父元素基线上移
六 用 vertical-align 实现垂直居中
1. 图片(inline-block 元素)居中
只需把父元素的行高设置为想要的高度,再给图片添加样式
vertical-align:middle
即可.
<div class="container" style="line-height:200px;">
<img src="../static/images/img1.jpg" style="vertical-align:middle;">
</div>
图 14 - 图片居中
需要注意的是这里的 "居中" 并不是严格意义上的居中,这里的 "居中" 是:图片的中垂线和父元素基线向上 1/2 个 "x" 字母的高度对齐.
2. 单行文本居中
<div style="line-height:200px;">
<p >xxx</p>
</div>
图 15 - 单行文本居中
3. 多行文本居中
把多行文本当成图片处理(对内可以设置宽高,对外是内联元素)
<div class="three">
<p class="three-p">
<span class="three-one">third</span><br>
<span class="three-two">third</span><br>
<span class="three-two">third</span>
</p>
</div>
<style>
.three{
line-height: 200px;
}
.three-p{
display: inline-block;
line-height:1.4em;
vertical-align: middle;
}
</style>
图 16 - 多行文本居中
七 直通地心的大坑:vertical-align:middle 失效
有一次进行测试的时候,发现
vertical-align:middle
失效了!代码如下:
<html>
<head>
</head>
<body>
<div class="container" style="line-height:200px;">
<img src="../static/images/img1.jpg" style="vertical-align:middle;">
</div>
</body>
</html>
什么?!!!代码完全没有问题啊?!!!!以前都是这样写的!!!!为什么不行了!!!
一个上午都在 debug,就是找不到问题在哪里!
后来一哥们觉得,既然代码都是一样的,那就是标准的问题了.
于是,在文档前面加了一句
<!DOCTYPE html>
.
居中了!!!!!
原来跟混杂模式还是标准模式有关!
所以使用这个属性一定要使用标准模式!
如果想要兼容旧浏览器,请加上一个空格来撑开行高:
<div class="container" style="line-height:200px;">
<img src="../static/images/img1.jpg" style="vertical-align:middle;">
</div>
来源: http://www.jianshu.com/p/1204f058432d