参考文章:

深入了解CSS的line-height属性

Vertical-Align: 你需要知道的所有事【译】

Vertical-Align: All You Need To Know

1、什么是行间距或者行高(line-height)

line-height是指文本行基线间的垂直距离。

1.1、顶线,中线,基线,底线

从上到下分别是顶线,中线,基线,底线。vertical-align的四个属性top,middle,baseline,bottom就是与这四条线有关。

1.2、行高,行距,半行距

  • 行高是指上下文本行基线间的垂直距离。(上图中两条红线间的垂直距离)
  • 行距是指一行底线到下一行顶线的垂直距离。(第一条粉线和第二条绿线间的垂直距离)
  • 半行距就是行距/2。(图中可以看出,半行距=(行高-字体size)/2 )

1.3、内容区,行内框,行框

  • 内容区:顶线和底线包裹的区域(字体的size)
  • 行内框:在没有其他因素影响的时候(padding等),行内框等于内容区。而设定行高时行内框高度不变,半行距分别增加/减少到内容区的上下两边(深蓝色区域)行框(line box)。(字体size不变,修改行高就是修改行距)
  • 行框:行框高度等于本行内所有元素中行内框最大的值(以行高值最大的行内框为基准,其他行内框采用自己的对齐方式向基准对齐,最终计算行框的高度),当有多行内容时,每行都会有自己的行框。

1.4、line-height的设置

百分比方式设置

<body>
121212
<p>121212</p>
</body>
body{
font-size:16px;
line-height:120%;
}
p{
font-size:32px;
}

line-height的百分比(120%)和body的字体大小(16px),被用来计算(16*120=19.2),这个值会被层叠下去的元素所继承。

补充

p{
font-size:32px;
line-height:60px;
padding:10px
}

最终盒模型

盒模型中,内容(不是上文说的内容区,上文的内容区是顶线与底线间的区域)的高度等于line-height的值。为什么会有margin?浏览器默认P的上下margin是1em,设置了P的font-size是32px,所以1em=32px。上下margin就是32px。

长度方式(px)设置

<body>
121212
<p>121212</p>
</body>
body{
font-size:16px;
line-height:20px;
}
p{
font-size:32px;
}

值normal

<body>
121212
<p>121212</p>
</body>
body{
font-size:16px;
line-height:normal;
}
p{
font-size:32px;
}

body的line的line-height是22px,所以normal等于1.375

p的line-height:32px*1.375=44px(normal并不是精确的等于1.375)

纯数字

就是将normal改为一个想要的准确数字。

1.5、各种BOX

<body>
<p>这个<em>强调</em> 元素为行内元素</p>
</body>
body{
font-size:16px;
line-height:1.5;
}
p{
font-size:32px;
padding:10px;
}

containing box

p就是一个containing box,包含了其他boxs。

inline box

在段落内,有一系列的inline box,inline box不会让内容成块显示,而是排成一行。“强调”是一种inline box,“这个”,“元素为行内元素”为一种匿名inline box。

line box

多个inline box组成line box,多个line box组成containing box。

Content Area

Content Area是围绕着文字的一种看不见的box,高度取决与font-size

inline box与line-height

font-size:32px,line-height:48px,行间距=48px-32px=16px,半行间距=8px。

半行间距会用在Content Area的顶部和底部。



这里inline box的高度就是line-height。inline box包着Content Area

但是,当line-height小于font-size。line box的高度还是line-height,所以line-box的高度小于Content Area的高度,Content Area会溢出line-box。

inline box 与line box

line box的高度取决于他内部最高的inline box。

2、vertical-align

vertical-align是用来对齐内联级元素的。设置为以下display属性的元素,它们都被认为属于内联级元素。inlineinline-block or **inline-table **(本文中不涉及此种情况):

inline内联元素基本上是包裹文本的标签。

inline-block内联块元素则如它们的名字所示:拥有内联特性的块元素。他们可以有width和height(可能是由自己的内容定义),以及padding、border和margin。

内联级元素彼此紧挨着放在一行中。一旦有更多的元素被放置到当前行中,一个新的行将会在它下面创建。所有这些行有所谓的“行框”,行框中包含所有的内容。不同大小的内容意味着不同高度的行框。在下面的插图中,行框的顶部和底部都是用红线表示的。

在行框中,元素的vertical-align属性是负责垂直对齐的。那么,到底元素垂直对齐的参照物是什么?

参照物:父元素的基线和外边缘

看看元素的基线和行框的外观:

inline元素

三行并排的文本。行框的顶部和底部边缘用红线表示,字体的高度由绿线表示,基线由一条蓝线表示。在左边,有一个line-height设置为与字体font-size大小相同高度的文本,绿线和红线重叠在一条线上。在中间,line-height是字体的两倍大。在右边,line-height是字体大小的一半大。

内联元素(display:inline)的外边缘与其行高的顶部和底部边缘对齐,行高可以小于字体的高度。所以,行框就是上面的图中的红线。

内联元素的基线是字符放置的位置线(字母x底部所在的水平线),即图中的蓝线。粗略地说,基线是在字体1/2高度的下面的某个地方。

inline-block元素

inline-block因为已经有宽和高,可能存在多行,每行都有自己的基线和行框,所以会比较特殊。

上图中,最外层是div,里面分别是三个inline-block的span,黄色为border,绿色为padding,蓝色为content area(一个span,其中有一个字母“C”)。左边的inline-block的span的内容(span)是一个正常文档流元素。中间的inline-block的span还额外加了overflow: hidden。右边的inline-block的span包含一个流外的span(但内容区域有一个高度)(译者注:流内的元素必须是普通文档流(normal flow)中的元素,流外的元素必须是浮动或绝对定位的元素以及根元素。)。蓝线为每个inline-block的span的基线。内联块元素的外边缘是其margin框的顶部和底部边缘,即图中的红线。

内联块元素(上图三个inline-block的span)的基线取决它包含的内容是否在文档流中:

  • 在流内内容的情况下,内联块元素的基线是正常流中最后一个内容元素的基线(左边的例子)。对于这最后一个元素,它的基线是根据它自己的规则找到的。
<div class="demo1">
x<span>
x<span style="display:inline-block;height:30px;width:100px;background-color:blue">x</span>
x
</span>
</div>
.demo1 span{
display:inline-block;
background-color:silver;
height:90px; }



灰色背景的元素内部有三个子元素,两个“x”,一个span。元素的基线就是最后一个正常流元素(“x”)的基线。

修改元素的长度,使其内容出现多行:

最外面的X怎么也跟着移动了?这涉及行框基线的移动,下文细说。

  • 在流内内容但内联块元素有overflow:hidden属性的情况下,基线是内联块元素margin框的底部边缘(例如在中间的图)。

    修改上面的例子样式:
.demo1>span{
display:inline-block;
background-color:silver;
height:90px;
width:100px;
margin:10px;
overflow:hidden;
}



通过最外面的x大致知道行框的基线位置,就是内联块元素的下外边距的地方,也是内联块元素元素的基线位置。

一开始此处有疑惑:内联块元素元素的基线跑到了下外边距处,那么元素里面的内容不应该以这条基线做定位吗?群里问了大佬,内联块元素已经设了宽高,可能有多行(即使只有一行),每行有各自的行框,然后又根据规则定位了,跟内联块元素的基线已经没有关系。

  • 在流外内容的情况下,基线是内联块元素margin框的底部边缘(例如在右边)。
<div class="demo1">
x<span>
<span style="display:inline-block;height:30px;width:100px;background-color:blue;">x</span>
</span>
</div>
.demo1>span{
display:inline-block;
background-color:silver;
height:90px;
width:100px;
}

加上浮动

<div class="demo1">
x<span>
<span style="display:inline-block;height:30px;width:100px;background-color:blue;float:left">x</span>
</span>
</div>

行框的基线是可变的

当使用vertical-align时,基线放置在哪里可能是最令人疑惑的部分。它需要满足vertical-align的值和行框的高度等所有条件。基线的位置犹如是方程中的一个自由参数。

行框的基线是看不见的,但你可以使它很容易看到。只要在文本行的开头添加一个字符,像我增加了一个“X”的字母。如果这个字符不以任何方式对齐,它将默认地坐在基线上。

围绕着行框的基线的部分(绿线),我们可以称其为文本框。文本框可以简单地被认为是行框内的内联元素,没有任何对齐。文本框的高度等于它的父元素的字体大小。因此,文本框只围住了行框内的无格式文本。由于这个文本框是绑在基线上的,当基线移动时它将移动。(注:此文本框在W3C规范中称为“strut(支柱)”)

vertical-align的值

1)将元素的基线,参照父元素的基线对齐

baseline:元素的基线与父元素的基线对齐。

sub:元素的基线偏移到父元素的基线之下。

sup:元素的基线偏移到父元素的基线之上。

:元素的基线相对于父元素的基线偏移了一个百分比(该百分比是对比元素自身的line-height计算得出)。

:元素的基线相对于父元素的基线偏移了一个绝对长度。

2)将元素的中心点,参照父元素的基线对齐

middle:将元素的顶部和底部之间的中心点,对齐父元素的基线之上x-height的1/2之处(x-height为字母x的字符高度)。

3)将元素的外边缘,参照父元素的文本框对齐

text-top:将元素的顶部边缘,对齐到父元素的文本框的顶部边缘。

text-bottom:将元素的底部边缘,对齐到父元素的文本框的底部边缘。

4)将元素的外边缘,参照父元素行框的外边缘对齐

top:元素的顶部边缘对齐到父元素的顶部边缘。

bottom:元素的底部边缘对齐到父元素的底部边缘。

基线的移动

如果一行中有一个高个的元素占据了整行的高度,那么vertical-align对它没有影响。它的顶部和底部没有空间让它移动。为了满足行框基线的对齐方式,行框的基线必须移动。矮个元素设置了vertical-align: baseline。在左边,高个元素设置了vertical-align: text-bottom。在右边,高个元素设置了vertical-align: text-top。你可以看到右边的基线跳起来了。

(左)将两个元素放在一行中并设置vertical-align ,它们会使得行框的基线移动到符合它俩的对齐规则之处,然后行框的高度也会随之调整。(中)添加第三个元素,不超越行框的边缘,既不影响行框的高度,也不影响基线的位置。(右)添加第三个元素,如果它超出了行框的边缘,行框的高度和基线调整。在这种情况下,我们的前两个元素也会跟着发生变化。

内联级元素底部的小间隙

列表项坐在基线上。下面的一点空间,是文本的基线以下预留的depth(在W3C规范中,一个字体的基线以上称为characteristic height,基线以下称为depth)。想要去掉这个depth空隙,有解决的办法吗?只要移动基线的位置就可以,例如通过设置列表项目vertical-align: middle

水平垂直居中

<div class="box">
<div class="content">
自适应垂直居中
</div>
</div>
html{
height:100%;
}
body{
height: 100%;
width: 100%;
}
.box{
display:inline-block;
text-align: center;
width:50%;
height:50%;
background-color:#e1e3cd;
overflow:hidden;
}
.box:after{
content:"";
display:inline-block;
height:100%;
vertical-align:middle;
}
.content{
vertical-align:middle;
background-color:silver;
display: inline-block;
width: 50%;
height:50%;
}

要将content水平垂直居中定位在box里,利用vertical-align是其中一种方法。原理是:vertical-align:middle(将元素的顶部和底部之间的中心点,对齐父元素的基线之上x-height的1/2之处(x-height为字母x的字符高度)。),content肯定是要垂直居中的,那只能修改行框的基线位置(注意:不是修改box的基线,box具有宽高,它里面的内容可能会有多行,每行有各自的行框,box的基线已经不会影响内容的布局,但是box的基线还是会受里面内容的影响(内联块元素的基线是正常流中最后一个内容元素的基线)),使其位于box的垂直中心位置。修改行框的基线,只要在box内加一个高度为100%的空元素,然后设置vertical-align:middle,添加的元素已经占满整个行框高度,而只要移动行框的基线,就可以满足定位规则,所以行框的基线就被移动到box垂直中心位置。content再按规则对齐到行框基线上就可以了。

最新文章

  1. hdu 1860统计字符
  2. 两两组合覆盖测试用例设计工具:PICT
  3. Force.com微信开发系列(八)生成带参数的二维码
  4. IIS网站程序无法访问oracle
  5. 1 。 LightOJ 1234 打表法(数据太大,把数据缩小100倍)
  6. onkeyup 事件会在键盘按键被松开时发生
  7. 经验总结17--submitbutton,ajax提交
  8. Effective C++:规定27:尽量少做动作的过渡
  9. iOS 实时录音和播放
  10. 【HTML】 HTML基础知识 表单
  11. 使用nginx缓存服务器上的静态文件
  12. 如何把checkbox做成radio一样的单选效果
  13. 进入正在运行的 docker 容器(docker container)
  14. P1186 玛丽卡 删边最短路最大值
  15. JavaSE——打印流
  16. iOS:ODRefreshControl
  17. some ideas
  18. 解决org.hibernate.QueryException illegal attempt to dereference collection 异常错误
  19. element ui 时间控件 多个日期
  20. cdn下载失败

热门文章

  1. Java中方法的重载和重置(覆盖)的区别
  2. AngularJS学习篇(二)
  3. python是如何进行内存管理的
  4. The Speed 歌词
  5. Could not load type &#39;System.ServiceModel.Activation.HttpModule&#39; from assembly &#39;System.ServiceModel, Version=3.0.0.0,&quot;解决办法
  6. hdu 6231 -- K-th Number(二分+尺取)
  7. 解决ajax的parsererror错误的终极办法(后台传给前台的数据json问题)
  8. Node做中转服务器,转发接口
  9. Spring的IOC容器第一辑
  10. canvas三环加载进度条