はじめに: タイトルの問題は、昨日午前中にさまざまなネットワークにこの問題について言及しましたが、今のところ返答はありません。明日はキャンパスの採用面接に参加するために早退しなければならないので、まだとても緊張していますが、問題は解決されておらず、よく眠れず、よく食べられません...それで、今でもこの問題をもう一度考え直すために最善を尽くしています。 、そして最後に、私が同意し、当面は明確な答えを見つけましたので、それをすべての読者と共有します。異なる見解、アイデア、意見、提案がある場合は、修正してください。
正式な議論の前に、ある現象を観察します (Chrome でのパフォーマンス、他のブラウザでのパフォーマンスと計算は若干異なる場合があります):
上の図に対応する HTML は次のとおりです (以降のすべての議論は以下に基づいています) this) :
<!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>
DIV と SPAN の高さを計算しましょう
document.getElementsByTagName('div')[0].offsetHeight//93document.getElementsByTagName('span')[0].offsetHeight//42
この写真について、作者は次のような質問をしています:
line-height は 32px ですが、SPAN の高さはなぜ 42px ですか?
DIV の高さは 93px ですが、これは IMG の高さにマージン 90px を加えたものと、SPAN の高さ 42px よりも大きくなります。どのように計算されますか?
画像やテキストの下のスペース(テキストがなくても存在します)はどのようにして発生しますか?
IMG を削除し、HTML 部分を次のように変更するとします。
<body> <div> <span>Some Text</span> </div></body>
この時点で計算する:
document.getElementsByTagName('div')[0].offsetHeight//32document.getElementsByTagName('span')[0].offsetHeight//42
新しい質問が再び来ます:
DIV の子要素の高さは 42px ですが、なぜですか? DIVの高さを「サポート」していませんか?
この記事では上記の問題について説明します。 5 つの知識ポイントをカバーします:
インライン ボックス (またはインラインの置換不可能な要素) の高さ
インライン置換可能な要素の高さ
行ボックスの高さ
行間隔と行の高さ
インライン書式設定コンテキストを確立するブロック ボックスの自動高さ
したがって、説明する前に、著者は、インライン ボックス、インラインの置換不可能な要素、インラインの置換可能な要素、ライン ボックス、インラインの概念を読者が理解していることを前提としています。コンテキストの書式設定。まだ少しよくわからない場合は、簡単に復習してください:
置換可能な要素、置換不可能な要素
簡単に言えば、置換可能な要素とは、特定の表示コンテンツがタグと属性に基づいて決定される必要がある要素を指します。この記事で説明する IMG 要素の具体的な表示内容は、src などの属性によって決まります。非置換要素は、その内容が直接表示される要素です。たとえば、DIV と SPAN についてはこの記事で説明します。
ブロックボックス
この概念はブロックフォーマットコンテキストの内容です。説明するとさらに複雑になります。ブロックボックスは通常、display:blockの置換不可能な要素です。インラインレベルの要素、インラインレベルのボックス、インラインボックス、インライン書式設定コンテキスト
display: inline|inline-table|inline-block はインラインレベルの要素を生成します。インライン レベルの要素はインライン レベルのボックスを生成し、これらのボックスはインライン書式設定コンテキストに参加します。
表示値が inline の置き換え不可能な要素は、インライン ボックスを生成します。
インラインレベルボックスではないインラインレベルボックスは、アトミックインラインレベルボックスと呼ばれます。
ラインボックスインライン書式設定コンテキストでは、ボックスは、それを含むブロックの上部から水平に次々に配置されます。すべてのボックスを一列に含む長方形の領域を行ボックスと呼びます。段落は行ボックスを垂直に積み上げたものです。
したがって、次の図 (大まかなトレース) が得られます:
今すぐ計算を開始してください!
1 ドキュメントフロー内のインライン置換可能要素およびインラインブロック置換可能要素の高さ計算
高さと幅の計算値が両方とも auto であり、要素に固有の高さがある場合、その場合、固有の高さは高さ使用値になります。
それ以外の場合、高さの計算値が auto で、要素に固有の比率がある場合、高さの使用値は次のようになります:
幅の使用値/固有比率
それ以外の場合、高さの計算値が auto の場合、および要素に固有の比率の高さがある場合、固有の高さが高さによって使用される値になります。
それ以外の場合、高さの計算値が自動であっても、上記の条件がいずれも満たされない場合、高さに使用される値は、2:1 の比率で最大の長方形の高さに設定する必要があります。 150px を超え、幅はデバイスの幅以下です。
つまり、この例では、IMG ボックスの高さは 80+10 = 90px です。
2 インライン ボックスの高さの計算
上で行ったように、JavaScript を使用してインライン ボックスの offsetHeight 値を取得する場合:
document.getElementsByTagName('span')[0].offsetHeight
著者は、この高さを、私たちがよく知っているブロック ボックスの高さに似て、「インライン ボックスのボックスの高さ」と呼んでいます。と 。計算される値は次のとおりです:
コンテンツ領域の高さ + 上下の境界線 + 上下のパディング = インライン ボックスのボックスの高さ
边框和内边距的宽度默认为 0,否则为我们自己指定,但“内容区域高度”是怎么计算的呢?
W3C 这么说:
height 不适用。内容区域的高度应基于字体,但本规范没有指定如何。用户代理可能,比如说,使用行高盒 EM-Box 或字体的最大上端部 Ascender 和下端部 Descender。(后一种会确保有部分在行高盒之上或之下的字符仍然落在内容区域内,但会导致不同字体有大小不一的盒子;前者则确保作者可以控制相对于 line-height 的背景设计,但也导致字符绘制在其内容区域之外。)
言下之意:
height 属性无效
行内盒内容区域高度在规范里面没有定义,浏览器可以自己折腾
既然规范没有明确规定计算,我们让浏览器实测一下。笔者浏览器测试如下:
Chrome 42
IE11 42
Firefox 43
如果我们更改字体,假设应用如下 CSS
body { font-family: Simsun; }
Chrome 33
IE11 37
Firefox 35
而如果我们修改 line-height,以上结果均不受影响。
笔者也曾疑惑,这个 offsetHeight 就是内容区域高度吗?答案:是。笔者的验证方法是基于 W3C 如下规定:
尽管不可替换元素的外边距、边框以及内边距不纳入行盒的计算,它们仍然渲染在行内盒的周围。这意味着如果 line-height 指定的高度小于被包含盒的内容高度,内边距和边框的背景和颜色可能“流进”毗邻的行盒。用户代理应当按文档顺序渲染这些盒。这会造成后面的盒的边框绘制在前面盒的边框和文本上。
您可以用以下代码实测,会发现红色行内盒的背景溢出到了黑色行内盒所在的行盒。
<div> <span style="background:red">Some Text</span> <br/> <span style="background:rgba(0,0,0,.5)">Some Text</span></div>
可知内容区域高度,即行内盒没有内边距和边框时的 offsetHeight。
因此总结论是:
行内盒的内容区域高度计算没有统一的标准,不同的字体或者不同的浏览器都可能导致不同的结果,且其高度与 line-height 无关。
由此我们无法确切地获得一个跨浏览器的行内盒的内容区域高度。同样我们也无法确切获得一个跨浏览器的行内盒高度(因为其计算式里面就包括了不定变量内容区域高度)。
但问题来了,不同浏览器都采用不同的行内盒内容区域高度,又如何能统一计算行盒以及块容器的高度呢?这个问题便导致了笔者在上面所提到的“计算行盒高度时的行内盒的盒高度”概念。
我们进入下一个话题,行盒高度计算。
根据规范,行盒的高度决定如下:
计算行盒内每个行内级盒的高度。对于可替换元素、行内块元素以及行内表格元素,高度是其外边距盒的高度;对于行内盒,高度是其 line-height。
行内级盒根据其 vertical-align 属性垂直对齐。如果它们对齐 top 或 bottom,它们必须以能最小化行盒高度的方式对齐。如果这些盒足够高,则有多种解决方案并且 CSS2.1 没有规定此行盒的基线的位置。
行盒高度是最上盒顶部到最下盒底部的距离。
懂了:W3C 尽管允许浏览器有自己的行内盒内容区域计算方式,但统一了一个行盒高度的计算方式:
计算行盒的高度时,针对行内盒,高度直接取 line-height。行内盒可以有边框、内边距、外边距,然而跟行盒的高度完全没关系!
根据此规定,我们很快可以得出,计算行盒高度时,SPAN 盒的高度取 32px。
接着,由于我们的 vertical-align 是默认的 baseline,因此,应当把盒的基线同父盒的基线对齐。如果盒没有基线,对齐盒的下外边距边缘与父盒的基线。也就是说,把 SPAN 盒的基线同 DIV 盒的基线对齐,把 IMG 盒的下外边距边缘同 DIV 盒的基线对齐。
下图是字体的基线、上下端线等位置信息
图片来源:http://blog.justfont.com/
笔者作图如下:
假设我们设 DIV 盒的基线是 0,则 IMG 盒的下边缘同 DIV 盒基线对齐;上边缘(上外边距边缘顶部)在高于基线 90px 处。而 SPAN 盒由于其基线对齐 DIV 盒基线,故其行盒下边缘略低于基线。
整个行盒的高度即 IMG 盒上边缘到 SPAN 盒下边缘。假设没有 IMG 元素,则高度为 SPAN 盒的 line-height。
但读者您可能注意到了,29 和 -3 是怎么得来的呢?下面,笔者带您算!
行間と行高さを計算すると、29と-3の2つの値が得られます。まず仕様を見てみましょう:
CSS は、各フォントがフォントのプロパティで指定されたベースラインより上の特徴的な高さと下の特徴的な深さを持っていることを前提としています。このセクションでは、(特定のフォント サイズの) 高さを表すために A を使用し、深さを表すために D を使用します。また、上から下までの距離である AD = A + D も定義します。 (TrueType フォントと OpenType フォントの A と D を見つける方法については、以下を参照してください。) フォントのこれらのプロパティはフォント全体を指しており、必ずしも個々の文字の上部と下部に対応しているわけではないことに注意してください。
ユーザーエージェントは、文字に対応するベースラインに従って、置換不可能なインラインボックス内で文字を配置する必要があります。次に各キャラクターのAとDを決めます。単一要素の文字は異なるフォントから来ている場合があるため、すべての A と D が同じになるわけではないことに注意してください。インライン ボックスに文字がまったく含まれていない場合は、要素の最初に使用可能なフォント (幅 0 の非表示文字) を使用した A および D のピラーが含まれているとみなされます。
次に、各文字に行間隔 L を追加します。ここで、L = 行の高さ - AD です。通常、行送りの半分は A の上に追加され、残りの半分は D の下に追加され、文字とその行送りがベースラインより上の完全な高さ (A' = A + L/2) と完全な深さ (D' = D+) になります。 L/2。
注意。 L は負の値になる場合があります。
すべての文字と文字の両側の半スペースを含むインライン ボックスの高さは、正確に行の高さです。
上記の規制で次の概念に遭遇しました: フィーチャーの高さ A、フィーチャーの深さ D、上部から底部までの距離 AD、完全な高さ A'、完全な深さ D'、行間隔 L。
特性値に関して、著者は Google で Web サイトを検索し、読者に次の Web サイトの使用を推奨しました:
http://fontsgeek.com/
中国でこのような専門的で絶妙なフォント Web サイトを見つけるのは本当に難しいと文句を言わなければなりません(もしかしたら私かもしれません 開き方が間違っています>_
OK、インスタンスで Microsoft YaHei のフォント プロパティを取得できます: Dcsender -536; Height 2703。
AD はコンテンツ領域の高さで、この場合は 42
D はフォントの下端 (ベースラインの下) の高さで、42*(536/2703) = 8
L = 32 - 42 = -10
したがって、D' = 8 + -10/2 = 3
つまり、内側のボックスの下端はベースラインから 3 ピクセル下にあります。同時に、インライン ボックスの高さは 32 ピクセルとみなされ、その上端はベースラインから 29 ピクセル上にあることもわかります。
行ボックス全体の高さは、IMG ボックスの上端から SPAN ボックスの下端までであると言いました。したがって、インライン ボックスの高さは 90 + 3 = 93px となります。
W3C CSS2.1:10.6.3 によると、高さはコンテンツの上端から最後の行ボックスの下端までです。ドキュメント フロー内のサブボックスのみが考慮され、相対的に配置されたサブボックスは無視されます。サブボックスは匿名ボックスである可能性があります。
この例では、DIV ボックスのインライン書式設定コンテキストにはライン ボックスが 1 つだけあるため、その高さはライン ボックスの高さ 93 ピクセルになります。