怎么解释line-heihgt值小于font-size值出现的情况?

<span>hello</span>
<div>world</div>

span{
  font-size: 100px;
  border: 1px solid red;
  line-height:10px;
}
div{
  border:1px solid;
}

代码如上,当span的font-size大于其line-height值,会出现下方的div会和span重叠了一部分,请问这个重叠部分的高度是怎么计算的?
代码:这里

示意图

阅读 5.5k
5 个回答

给个终极解释吧。只说 CSS2.1标准,不说浏览器的兼容性。

简化的答案是span里面字体的“深度”减去所在行框的“深度”

这个高度还真的不太好计算,分不同的字体,因为不同字体的的baseline的位置不一样,同样字号的不同字体大小也不一样(标准里都没说怎么计算)。行内元素的位置根据vertical-align对齐所在的行框。所以要计算行内元素的位置就要先计算行框的高度,然后根据vertical-algn确定行内元素的位置,再根据元素的大小计算覆盖的大小。覆盖的高度理论上可以计算,可是涉及一些上述值的不同(而且未知),就显得没办法计算了。告诉你计算方法,自己想办法实现。

先看看如何计算行框(line box)的高度。
displayinline,inline-block等这样的元素,他们其实也是一个“block”,也有一个高度(见后面)。为了排版这些元素,CSS规定了一个行框(line box),这个行框就是一个正常的类似divdisplay:block的元素,行内元素就这样从左到右“堆”在行框里面,行框的高度通过某种方式计算。

CSS2.1 是这样计算的:

  1. 计算所有行内元素的高度。inline-box的高度就是这个元素的margin box的高度,就是margin外边缘的高度。inline这种“block”的高度,就是line-height设置的高度,而不管其中的元素占用了多少位置。就像给block设置高度之后,即使无论其中有多少元素,block就是占用那么大的高度。

  2. 每个元素根据设置的vertical-align放入这个行框。其实这个与行框的高度有关,这是一个相互依赖的关系,可能有多个解,尽量使得行框的高度最小。但是这样也不能保证只有一个解,所以出现这种情况就真的看浏览器的实现了。

  3. 行框的高度就是最上“block”的上边缘与最下"block"下边缘的差值。

可见,对于inline的元素,其高度就是line-height设置的高度,而不管其中字体到底有多大。因此,span占用的高度就是 line-height设置的 10px;无论其中的字体是多大。于是行框的高度就是10px。那么如果字体大于10px,就会出现类似div设置了一个较小的高度,其中内容又太多,overflow:visible的效果。
如下效果,hellog xxmmggg 的位置不同,是因为他们的vertical-align不同(上述第二条)。后面的block就是display:block设置了一个小的高度的结果。
再说这个 vertical-align可取的值其他值还好吧(不常用或是可计算),但是有个baseline,而且是默认值。对于字,根据字体可能位置不同。inline-table的baseline是其中第一行字的baseline,inline-block 的baseline是其中最后一行字的baseline,如果其中没有字,其baseline就是包括margin在内的这个元素的下边缘。
baseline 到字体下边缘的高度叫做字的“深度”。因此,楼主的例子的话,覆盖的高度应该是span里面字体的“深度”减去所在行框的“深度”(当然还要考虑有多行的问题)。 字的“深度”取决与字体字号,行框的深度取决于其中的内容。。。。。涉及太多写不下去了,先写到这吧
图片描述

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <style>
span{
  font-size: 50px;
  border: 1px solid red;
  line-height:10px;
}
.baseline { vertical-align:baseline;}
.middle  {vertical-align:middle;}
.block {display:inline-block;height:10px;vertical-align:middle}
div{
  border:1px solid;
}
</style>
</head>
<body>
  <div>world</div>
  <div>world</div>
  <div>world</div>
  <div>world</div>
  <div>world</div>
   参考位置 xxmmgg
   <span class="baseline">hellog</span><span class="middle">xxmmggg</span><div>world</div>
  <div>world</div>
  <div>world</div>
  <div>world</div>
  <div>world</div>
  <span class="block">block</span>
    <div>world</div>
  <div>world</div>
  <div>world</div>
  <div>world</div>
</body>
</html>

div元素作为一个块级别元素会接在其它元素后面时,会发生折行,形成自己的的块级框,这个块级框的上顶部和前一个元素的块级别框(行框)的底部对齐

问题中的span是一个行内元素,内部hello文本形成一个行框,这个行框的的line-height为10px,font-size:100px;加到文本内容区行间距为(10-100)/2=-45px;形成的效果为span hello文本将向上移动45px(相对于line-height:100px;font-size:100px),有一部份文本看不到;行框底部也相应的上移动了45px

div world将被放置相应的位置~~~~(100+(-45))==55px;

我认为那个位置是基线与行框之间的差距,只要行高小于字体大小。那个位置的大小应该是取决于字体及字体大小。

div的折行是以span的行框(line box)的下边沿开始算起的。而行框的下边沿,在行高小于字体大小时,是在基线的上方。

你可以给span加上 vertical-align: top; ,会发现div 跳上去了。

时间不够,就不补图了

这个问题挺有难度的,我觉得主要有这样几个要点(需要先了解CSS2.1的规范细节):

  1. <span>元素外会生成一个匿名块元素,这个块元素的高度和<span>的内容高度无关,而取决于行框(line box)的高度。

  2. <span>这个行内非替换元素的内容高度等于font-size,但<span>产生的行内框(inline-level box)的高度等于line-height

  3. <span>元素的红色描边,体现的是元素的内容高度(我们常说的盒模型),而不是它产生的行内框。

  4. 无论有没有内容,行框内一定有一个默认文字形成的行内框以baseline对齐方式参与对齐(下图的"asp中文")。

  5. 文字在baseline之上的部分(Ascender)以及baseline之下的部分(Descender),遵循字体本身的特性进行分配(题主的应该是SimSun默认宋体),可以通过字体特性数据计算出baseline以下及以上的具体高度。

计算过程如下(其中用到了fontsgeek给出的SimSun的字体特性数据):

计算

其中位于中部的图给出了两个行内框的对齐排列状况,行框的高度将由此决定。
公式L = 'line-height' - ADD' = D + L/2来自于w3c Visual formatting model details

这个要看浏览器实现吧,比如我用的猎豹极速模式就不会有重叠

clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏