CSS中line-height与vertical-align

参考文章:
深刻了解CSS的line-height属性
Vertical-Align: 你须要知道的全部事【译】
Vertical-Align: All You Need To Knowhtml

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

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

1.一、顶线,中线,基线,底线

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

1.二、行高,行距,半行距

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

1.三、内容区,行内框,行框

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

1.四、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),这个值会被层叠下去的元素所继承。
spa

补充.net

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

最终盒模型3d

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

长度方式(px)设置orm

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

值normalhtm

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

body

body的line的line-height是22px,因此normal等于1.375

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

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

1.五、各类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。

二、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再按规则对齐到行框基线上就能够了。

相关文章
相关标签/搜索