行内盒的 offsetHeight 大于其 font-size

由于字体的不同,可能造成行内盒的 offsetHeight 大于其 font-size

例:http://codepen.io/HaoyCn/pen/WQOXgj

请问以下各值如何计算:

  1. 该行内盒的内容区域高度

  2. 浏览器实际渲染出的字号

  3. 行距 L = line-height - AD 中 A 和 D 取值

第一个问题是为了区别行内盒的内容区域高度和盒高度。按 W3C 在计算行盒时候的说法,该行内盒高度应为 line-height,但比如在上面链接案例中,line-height 等于 font-size 即 32px。而 W3C 未定义行内盒内容区域高度,所以我猜想这个 offsetHeight 是否就是各用户代理采取的内容区域高度。

第二三个问题关乎块容器高度之计算。如下 HTML:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Line Height</title>
<style>
body {
    margin: 0;
    font: 32px/1 'Microsoft YaHei';
}
div {
    width: 400px;
    margin: 30px auto;
    outline: 1px solid black;
    background: #008E59;
}
img {
    height: 80px;
    margin-top: 10px;
}
</style>
</head>
<body>
    <div>
        <span>Some Text</span>
        <img src="picture.jpg" alt=""/>
    </div>
</body>
</html>

SPAN 盒基线 和 IMG 盒下外边距边缘是基于 DIV 盒基线对齐,DIV 盒总外高 93px,IMG 总外高 90px。多出的 3px 我认为应为 L/2 + D

根据 W3C,AD 是同字体的特性深度和高度紧密相关的,现查得:

Microsoft YaHei,Ascent 2167,Descent 536,Height 2703。

数据来源:
http://fontsgeek.com/ 查询结果
http://www.zhihu.com/question/20137844 厉向晨的回答

用比例换算 A 和 D 的时候,采用的是 offsetHeight 还是 font-size 呢?

我试着计算了,似乎取 offsetHeight 更接近。但换字体换字号后误差还会扩大(可能是我查阅到的数据有误>_<)。

谢谢您的关注和回答!

阅读 4k
2 个回答

题主自问自答的文章已看。应届毕业生就已经了解到这种程度,佩服。

在此回答一下我对这部分内容的理解。

首先,是offsetHeight的概念。参考MDN对offsetHeight的说明可知,它是取盒模型的border box的高度。不过,需要注意的是,这和行内格式化上下文(inline formatting contexts, IFC)里行内级盒(inline-level box)的高度,并不是一回事。

10.8 Line height calculations对行内级盒的高度的描述:

The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.

也就是,对行内非替换元素(比如普通文字),行内级盒的高度等于line-height的计算值。对行内替换元素(比如和文字搭在一起的图片),行内级盒的高度等于其margin box的高度。显然,这不一定等于offsetHeight。行内级盒的高度更像是一个逻辑的概念,用来帮助确定行盒(Line box)的高度。

因此,题主文章里提到offsetHeight时将其称为“行内盒的盒高度”,这可能不妥。不过题主后文的分析计算很正确,行盒高度的取得过程大致描述为:将不同类型的行内级盒,按照其vertical-align特性进行对齐后,再取这些行内级盒的最高的顶边,到最低的底边,就得到行盒的高度。

其次,是作为容器的块元素的高度10.6 Calculating heights and margins对普通流的块级非替换元素(block-level non-replaced elements in normal flow)的高度的描述:

The element's height is the distance from its top content edge to the first applicable of the following: 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines ...

也就是说,如果这个用作容器的块元素建立的是IFC,单行或多行均可,那么它的内容区高度,就是从自己的content box的顶边,到最后一个行框的底边。所以,对建立IFC的容器而言,其高度由内部的行框的高度决定。

最后,是有关排列文字的行内非替换元素的高度。题主的文章也说了,在默认情况下,浏览器(UA)会保证元素的内容区,始终包含文字的上端部Ascender和下端部Descender,因此使用不同的字体时,将得到不同的内容区高度。

L = line-height - AD 的计算式中,AD就是指在浏览器考虑了字体特性后,为对应字体给出的内容区高度。所以准确地说,既不是offsetHeight,也不是font-size,而是content box的高度。

题主的问题也让我理解了为什么一个容器里单放一个图片总是要多那么一点缝隙 :) :

缝隙

ps. inline-level elements、inline-level box、inline box这些概念的英文原名就已经很容易弄混了,所以我倾向于不翻译而直接用术语英文原名。

推荐问题
宣传栏