假装异步加载中...
10 Dec 2013

第二天,谈谈【line-height】

先来看MDN上的总结:

  • On block level elements, the line-height CSS property specifies the minimal height of line boxes within the element.
  • On non-replaced inline elements, line-height specifies the height that is used in the calculation of the line box height.
  • On replaced inline elements, like buttons or other input element, line-height has no effect.[1]

也就是说:

  1. block level elements(块元素)上使用line-height,也就指定了块元素内部line boxes的最小高度
  2. non-replaced inline elements上使用line-heightline-height会被用来计算line boxes的高度。
  3. replaced inline elements上使用line-height没有效果。例如:button或者其它input标签。[1]

第3条规则看起来最容易理解,我们先拿它来实验下,看测试用例一:

.button-1{
    line-height: 20px;
}
.button-2{
    line-height: 30px;
}
.input-1{
    line-height: 20px;
}
.input-2{
    line-height: 30px;
} 效果如下:

enter image description here

enter image description here

出人意料的是在replaced inline elements上使用line-height居然有效果,与第3条规则不符。注意到第3条规则是有注解的。还好,注解里给出了原因:

[1] Neither engine implements the correct behavior with replaced inline elements like buttons. In some cases line-height is allowed to have an effect on them. This is incorrect behavior relative to the specification.

也就是说浏览器都没有正确的实现这一效果。按照CSS规范来看,浏览器在这一效果上都错了。

接着来看第2条规则:

  • non-replaced inline elements上使用line-heightline-height会被用来计算line boxes的高度。

至于到底如何计算,它并没有说明。在介绍计算规则之前,需要先明确几个概念。用代码说话:

<p>
    The <em>emphasis</em> element is defined as "inline".
</p>

显示效果如下:

enter image description here

上面的代码涉及到了四种盒子:

1 . block-level boxes(块级盒),由代码中的<p>标签产生,它可以包含其它的box

enter image description here

2 . inline-level boxes(行级盒),在<p>标签中有一系列的inline-level boxes,如下:

enter image description here

上面的inline-level boxes可以分为两类,一类是由内联元素产生的,例如<em>

enter image description here

而余下的两个没有被标签包裹的inline-level boxes就被称为anonymous inline-level boxes(匿名行级盒),如下:

enter image description here

3 . line box,由inline-level boxes连接而成,每一行称为一个line box

enter image description here

4 . content area,它是围绕着文字的并且看不见的一种box,它的高度取决于font-size。如下:

enter image description here

概念介绍完了,回到我们的问题上:

non-replaced inline elements如何根据line-height来计算line boxes的高度

上面我们说过line box是由inline-level boxes连接而成,所以我们将问题拆成两步:

  1. 先探究line-heightinline-level boxes高度的关系
  2. 再看inline-level boxes的高度与line box高度的关系

先来看看line-heightinline-level boxes高度的关系,测试用例二:

再结合下面这张图

enter image description here

你应该就能看明白了。

我们把line-height: 30pxfont-size: 20px的差值10px称为行间距(英文是leading)。那么半行间距(英文是half-leading)就是 10px / 2 = 5px 。半行间距作用在content area的顶部和底部。

enter image description here

很简单,对不对?

但是别忽略了,上面计算的前提是line-height大于font-size,那如果line-height小于font-size会怎么样呢?来看测试用例三:

我们看到当line-height小于font-size时,inline-level boxes会使用line-height作为自己的高度,此时 content area溢出 inline-level boxes ,如下图所示:

enter image description here

那么如果将line-height设置为0会出现啥效果呢?我们以后再探究。

至此,我们说完了line-heightinline-level boxes高度的关系,接下来该看inline-level boxes的高度与line box高度的关系了。记住下面这条规则:

line box 的高度由它内部 最高的 inline-level boxesreplaced element 来决定。

来看测试用例四:

至此,我们终于清楚了line-heightline boxes高度的关系,也就清楚了 MDN上第2条规则的含义:

  • non-replaced inline elements上使用line-heightline-height会被用来计算line boxes的高度。

需要补充的一点是:line boxes 在它的容器里是紧挨着彼此堆叠到一起的,看下图会更好理解一些:

enter image description here

最后,我们来看第1条规则:

  • block level elements(块元素)上使用line-height,也就指定了块元素内部line boxes的最小高度

理解这一条需要一点想象力,看着下图,开动你的想象力:

enter image description here

想象在每一个line box的起始位置都有一个宽度为零的 inline-level boxes ,我们把这个想象出来的盒子叫做strut(这个名字来源于TeX)。strut会根据继承来的font-sizeline-height 计算本身所占高度。这个高度也就是所在line boxes的最小高度。

参考文献:

  1. http://www.w3.org/TR/2011/REC-CSS2-20110607/visudet.html#line-height
  2. http://www.w3.org/TR/css3-box/
  3. CSS布局
  4. 一个关于line-height非常好的PPT,本文部分图片来自这个PPT,需翻墙

说了这么多有关line-height的问题,其实还有好多知识点没有涉及到,比如line-height的继承问题以及0行高问题等等。我们后面会一一探讨。

发现文章有错误或是有疑问,欢迎骚扰:395217502@qq.com
comments powered by Disqus