<small>标签会使段落的高度变大。

14

我有以下的fiddle:

http://jsfiddle.net/tompazourek/sn5jp/

<p>some normal-sized text</p>

<p>some <small>small</small>-sized text</p>

p { line-height: 20px }

当我在Chrome中检查页面时,我发现第一个段落的计算高度为20px,但第二个段落的计算高度为21px。
为什么标签会导致这些问题?我该如何解决?
段落文本中每个标签的出现都会破坏我的基线网格

编辑:我后来还发现了一篇与此主题相关的有趣文章:深入探究CSS:字体度量、行高和垂直对齐


1
这真的很神秘。如果你用span元素替换small元素,并测试不同的字体大小,你会发现任何比父元素字体大小小(即使只有一个像素)的东西都会使父元素高度为21px,而大于19px的较大字体大小则不会这样做(高度保持在20px)。 - Jukka K. Korpela
4个回答

14

解释:

这里有几件事情发生了。

在你的示例中,small元素是一个行内级元素,这意味着它的垂直对齐方式由vertical-align属性决定。

默认的vertical-align值是baseline,这意味着small元素的基线将与父盒子的基线对齐:

使盒子的基线与父盒子的基线对齐。如果盒子没有基线,则将底部边缘与父基线对齐。

接下来,需要考虑line-height属性以及其如何计算。还需要考虑前导和半导。在CSS中,半导是通过找到元素的line-heightfont-size之间的差异,将其除以二,然后在文本上方和下方放置计算出的空间量来确定的。

为了说明这一点,这里有一个示例图像(来自W3.org):

enter image description here

由于line-height20px,而small元素的font-size13px,因此我们可以确定small元素文本上下方添加了3.5px的空间:

(20px - 13px) / 2 =  3.5px

同样地,如果我们计算周围文本节点的半行高,这些文本节点具有 font-size16px,那么我们可以确定在周围文本上方和下方添加了 2px 的间距。

(20px - 16px) / 2 =  2px

现在,如果我们把这些半导行空间的计算与 vertical-align 属性联系起来,你会注意到实际上在 small 元素基线下方添加了更多的空间。这就解释了为什么包含 small 元素的 p 元素的计算高度要大于其他 p 元素的计算高度。

话虽如此,你可能会期望随着 small 元素的 font-size 减小,p 元素的计算高度会继续增加。为了进一步说明这一点,你会发现当 small 元素的 font-size 设置为 6px 时,p 元素的计算高度为 23px

p { line-height: 20px; }
small { font-size: 6px; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>

潜在解决方案:

由于我们知道高度差是由于 baseline 增加的额外空间造成的,因此我们可以将 small 元素的 vertical-align 值更改为 top


p { line-height: 20px; }
small { vertical-align: top; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>

或者,你可以给small元素设置line-height: 17px,这会在元素上下各添加2px的空间(和我们之前计算出来的文本周围添加的空间量相同)。

// Surrounding text that is 16px:
(20px - 16px) / 2 =  2px

// Small element text that is 13px:
(17px - 13px) / 2 =  2px

p { line-height: 20px; }
small { line-height: 17px; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>

然而,你真的不想计算任何这些内容并硬编码它们,这意味着你应该只使用相对的 line-height 并省略 px 单位。

由于 font-size16px,所需的 line-height 值为 20px,因此你需要将 line-height 除以 font-size 并得到 1.25

p { line-height: 1.25; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>

如果您不想使用相对的line-height: 1.25,而希望继续使用line-height: 20px,那么您当然可以将small元素的line-height值重置为初始值,即normal

p { line-height: 20px; }
small { line-height: normal; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>


好的,你找到了解决问题的方法。为此我向你致敬 :). 但是,仍然存在一个问题,即顶部对齐的 <small> 文本看起来很奇怪。此外,我仍然不真正理解底层发生的原因和机制。 - Tom Pažourek
2
是的,我刚刚在某个地方又注意到了这个问题,并认为它值得得到适当的解释。再次感谢您提供这么详细的答案 :) 看起来很不错。我会保持问题开放一段时间,但看起来您将赢得悬赏。 :) - Tom Pažourek
1
现在这是一个好问题和好答案的组合,我很久没有见过了。我已经思考这个问题很长时间了,但是无法解释清楚。谢谢你们两个 :) - AVAVT
@JoshCrozier 我今天仔细再次阅读了您的答案,但我仍然无法理解其中的一切。在 vertical-align 工作区域之前,我能够理解您所说的内容,但后面的三个 line-height 工作区域中仍然涉及到我不太明白的东西。我创建了另一个代码片段,其中文本被拆分成两行,第二段只包含具有 line-height: 17px<small> 文本。我不明白的是为什么两个段落的高度仍然相等为40px。我认为如果 <small> 设置行高为17px,它应该只有34px的高度。 - Tom Pažourek

1

与 Josh Crozier 发布的答案不同的是,另一种方法是彻底重置小的行高:

p { line-height: 20px }
small {line-height: initial;}
<p>some normal-sized text</p>

<p>some <small>small</small>-sized text</p>


0

您可以使用相对值来设置 line-height。在您的情况下,基础字体大小为16px,因此以相对单位设置为20px的行高将是 1.25

p { line-height: 1.25; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>


0
这是因为小标签的字体大小设置为smaller,而p标签的大小比小标签大,所以造成了小标签和p标签之间的差异,从而导致了这个问题。当你将小标签放入p标签中时,会增加高度,因为小标签所占据的空间比p标签小。
要解决这个问题,你需要给小标签添加行高为19px,就像这样:

p { line-height: 20px }
small{line-height: 19px}
<p>some normal-sized text</p>

<p>some <small>small</small>-sized text</p>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接