为什么在这个例子中,无单位的行高与百分比或时间行为不同?

我为以下CSS的行为困惑,也在这个小提琴中说明。

<style type="text/css"> p { font-size: 14px; } .percentage { line-height: 150%; } .em-and-a-half { line-height: 1.5em; } .decimal { line-height: 1.5; } .smaller { font-size:50%; } .caption { font-weight: bolder; font-size: 80%; } </style> <p class="caption">default line spacing</p> <p>This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p>This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 150%</p> <p class="percentage">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="percentage">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 1.5em</p> <p class="em-and-a-half">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="em-and-a-half">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 1.5</p> <p class="decimal">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="decimal">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> 

前两个段落有默认行间距。 第二段有一个字更小。 但是它不会影响该段落中的行间距。 不是这样,但是,

接下来的两段有line-height: 150% 。 再次,第二段有一个更小的词。 但这一次,由于原因不明,较小的字体在前两行之间创造了额外的空间(至less在Safari,Chrome,Firefox和Explorer中)。 这是我正在尝试修复的CSS中的原始问题。 (我推测这与浏览器收缩有关,然后垂直下移以重新调整基线。)

接下来的两段有line-height: 1.5em 。 我的理解是1.5em150% 。 事实上,行为是一样的:第二段的前两行之间有额外的空间。

但是这里有个奇怪的地方 :接下来的两个段落有line-height: 1.5 – 没有指定单位。 这一次,额外的空间问题就消失了。

总而言之,当父&子的行高不同(通过inheritance无单位值)时,CSS似乎给出了一致的行间距结果,但当父&子的行高相同时,结果却不一致。

因此我的问题:

  1. 我知道CSS规范在1.5150%之间或者它的同义词1.5em是有意的语义差异。 (即:一个无单位的值被传递给子元素,它的行高是使用孩子的字体大小来计算的,而百分比或em值会导致父母的行高,然后计算出的值被传递给孩子)。但是,这是如何解释这里所看到的行为差异呢? 多余的空间来自哪里? 如果这是一些CSS定位规则的后果,那么这个规则是什么?

  2. 或者,如果这些例子都应该以相同的方式呈现,那么哪一个是不正确的实施? (关于Q2的注意事项:在不同的浏览器中,渲染怪癖发生的方式相同,这强烈地表明它们都没有被错误地执行,这会带你回到问题(1)。)

  3. 实际上,切换到无单位测量,如line-height 1.5是否有缺点? (答案:否)

根据提出的答案中的线索,我认为在这些示例中看到的渲染行为是违反直觉的,但是是正确的,并且由规范中的几个规则的交互以及整体的CSS盒模型来规定 。

  1. CSS通过公式line-height = L + AD计算一个框所需的前导L,其中AD是字体的“从顶部到底部的距离” 。 然后“领先的一半加在A以上,另一半加在D以下”。 因此, font-size:16pxline-height:24px文本将具有4px的上下。 font-size:8pxline-height:24px文本将有8px的上下。

  2. 然而,默认情况下, “用户代理必须按照其相关基线alignment字形…”。 。 这开始解释这里发生了什么。 当line-height由百分比或em指定时,计算值由子代inheritance(此处为smaller跨度)。 意思是, smaller跨度与父块具有相同的line-height 。 但是由于L + AD的公式,这个跨度的文本在上下都有较多的领先,因此基线在它的框中位置更高。 浏览器垂直下推smaller跨度以匹配基线。

  3. 但是,那么浏览器有一个新的问题 – 如何处理封装块中的线间距,这已经被这个基线调整过程打乱了。 该规范也解决了这个问题:块级元素的line-height “指定元素内线框的最小高度” 。 也就是说,CSS不能保证你会得到你的确切的line-height ,只是你至less得到了这个数目。 因此,浏览器将围栏中的线条分开,以便重新排列子框。

这是对立的原因是,这是大多数文字处理器和页面布局程序工作的反面。 在这些程序中,一段文本中的一小段文本由其基线(如CSS)排列,但行高作为基线之间的距离强制执行,而不是围绕较小文本的框。 但是这不是一个错误 – CSS是围绕框模型devise的。 所以最后我们可以说这个间距行为是这个模型的结果。

这仍然让我们解释在无单位行高的例子中的行为:

  1. 首先,请注意,如果未指定行高,则默认情况下,浏览器将应用无单位的行高。 这是规范所要求的 : line-height的初始值是normal ,它被定义为“与<number>相同的含义”,并且该spec推荐值“在1.0和1.2之间”。 这与我们在上面的例子中看到的是一致的line-height: 1.5的段落与没有line-height设置的段落具有相同的行为(也就是说,它们意味着获得line-height: normal

  2. 正如其他人所指出的那样,当段落的line-height: 1.5时,段落的计算行高不会被smaller跨度inheritance。 smaller跨度根据自己的字体大小计算自己的行高。 当段落有line-height: 1.5; font-size: 14px line-height: 1.5; font-size: 14px ,那么它的计算行高是14px * 1.5 = 21px。 如果smaller跨度只有font-size: 50%的字体大小,那么它的字体大小是14px * 50%= 7px,线高度是7px * 1.5 = 10.5px(通常会四舍五入到整个像素) 。 但总的来说, smaller盒子是周围文本的一半。

  3. 和以前一样,浏览器会将smaller跨度与相邻的基线垂直alignment。 但是这一次,因为周围的smaller比周围的文本短,所以这个重新排列在封闭块中没有任何副作用。 它已经适合,所以没有必要像以前那样传播父段的内容。

这两种情况代表了规范的一致的实现。 这是个好消息,因为这意味着我们可以预测行间距行为。

这使我们回到了这个问题的原来的原因。 虽然我现在明白,CSS盒模型需要这种行为,作为练习印刷工,这很less是我想要的行为。 我想要的是,段落中的线条具有一致且精确的线条间距,即使该段落中的一些文本跨度较小。

不幸的是,似乎没有办法在文字处理器或页面布局程序中直接执行CSS中的精确行距。 同样,这是因为CSS盒模型:它不使用基线到基线行间距模型,并且line-height被指定为最小测量值,而不是最大值。

但是我们至less可以说,单位线高值在CSS中产生了精确线间距的最佳近似值 。 像我这样的挑剔的印刷工人应该感觉舒适,因为无规格的价值得到了规范的支持 ,并且在浏览器中产生了一致的结果。 他们不是黑客,也不被弃用。

警告是,他们仍然只是一个近似。 无单位的行高值不会更改底层的CSS框模型,也不会更改CSS框定位规则。 所以在某些边缘情况下,他们可能没有预期的结果。 但永恒的警惕是良好的版式的价格。 在那里小心点。

编辑

我创build了一个codepen来演示使用不同值创build的主导 。 希望这提供了一个更好的解释。


我可以回答你的问题,但只能对你看到的额外空间(在这一点上)进行推理(并提供潜在的解决方法)。

你的问题

CSS和1.5%到150%之间是否存在有意的语义差异,这说明了行为差异?

实际上有!

数字因子(本例中为1.5)被inheritance并用于计算每个后代相对于其字体大小的行高。

百分比因子(150%)用于根据父元素的字体大小计算行高。 所得到的预先计算的值然后由其后代inheritance。

或者,如果他们的意思是一样的,那么哪一个是不正确的实施?

他们故意不同。 (请参阅W3C规范 )

实际上,切换到原始小数如1.5是行高吗?

通常,使用十进制值是一个优点,因为inheritance的行高会更好地适应。 但有些情况不适合您的需求。


额外间距问题

我注意到,如果我将vertical-align设置为middlebottom小文本,则问题不会发生。 但这不是一个很好的解决scheme。

这是因为较小的文本使用了inheritance的计算行高,结合它在行上的位置。 由于文字较小且位置较低,但线条高度与周围线条相同,所以下半部分将会进一步向下,而上半部分不会像周围文本那样高。

所以我们假设基础字体大小是16px,行高是24px。 (24-16)/ 2)。 当字体大小是50%,即8px,但行高保持24px。 所以领先的是两边8px((24-8)/ 2)。

文本的基线将alignment,所以所有的东西都是平等的,你会期望较小的文本扩展到普通文本以下4px。 但是,由于文本(及其相应的内容区域)较小,所以下半部分的引导开始更靠后,这就是为什么你只看到一个像素或两个变化,只有一定的百分比(越小越好 – 试一下出)

我真的应该使用这个图像,但现在不能这样做,也许我可以稍后添加一些。

我不知道这是否有帮助,但是我现在对line-height工作状况一定有了更好的了解!

参考文献: http: //www.w3.org/wiki/CSS/Properties/line-height http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/ http:// www .maxdesign.com.au /用品/ CSS-行高/

看来你的问题的简单答案将是: inheritance 。 在你的例子中, line-height: 150%line-height: 1.5eminheritance父级的计算机值,而数值不会。

在你的例子中,父<p>的行高为21px,如果你使用百分比或者ems来指定你的嵌套元素的行高<span class="small"> ,它将根据inheritance的计算值21px; 21 * 1.5 = 31.5,但是如果你使用数值作为行高,它将根据实际的字体大小来计算; (14 * 0.5)* 1.5 = 10.5。

你在这里有一个完美的答案。

马修,尝试添加“行高:1.5em”到“.smaller”类。 它是否解决了所有声明的问题?

我认为如果会的话,那就必须是遗产问题。 1.5em / 150%和1.5(没有任何单位)之间的区别在于,前两个计算值并将其设置为其元素上的绝对值,因此该元素的子元素没有自己的行高声明将inheritance计算值,而不是百分比。

然而,声明没有单位的行高对于那个子元素来说有不同的结果,因为实际上inheritance的是那个数字(在你的情况下是1.5),这个数字将会再次在子元素上被计算,从而产生一个相关的值到它自己的字体大小,而不是它的父母的。

你说规范定义了所有的版本,所以结果应该是一样的,但这里是实际说的:

 <number> 

使用的属性值是这个数字乘以元素的字体大小。 负值是非法的。 计算的值与指定的值相同

 <percentage> 

该属性的计算值是该百分比乘以元素的计算字体大小 。 负值是非法的。

这是不同的:实际计算的是什么。 当你以百分比(或使用ems)声明行高时,计算值就是结果的数值,而在无单位声明的情况下,计算值与声明值相同,使得子元素重新计算。

与此同时,我做了testing,我认为我是对的。

当您以百分比(或使用ems)声明行高时,计算的值将由span元素inheritance。 所以span元素的行高将是24px而不是13.5px。 但是,由于span元素的字体大小实际上较小,所以下面的导致的结果会比其父项大。 (24像素-9px)/2=7.5px。 所以你会得到7.5px而不是(24-16)/ 2(4px)。 你最终会有一个额外的7.5px-4px(3.5px)领先。