line-height
と
vertical-align
は単純なCSSプロパティです。 とても単純なので、私たちのほとんどは、それらがどのように機能し、どのように使用するかを理解していると確信しています。 残念ながら、これはそうではありません-実際、これらは「インライン書式設定コンテキスト」と呼ばれるあまり知られていないCSS機能の作成に重要な役割を果たすため、おそらく最も複雑なプロパティです。
たとえば、
line-height
は長さまたは無次元の値として指定できますが、デフォルト値は
normal
です。 わかりましたが、「標準」とはどういう意味ですか? 多くの場合、これは(原則として)1、または1.2であると書いています。 CSS仕様でも、この質問に対する明確な答えはありません 。
無次元の行の高さの値は
font-size
値に依存することがわかっていますが、問題は
font-size: 100px
がヘッドセットによって異なるように見えることです。 この点で、問題が発生します:
line-height
常に同じでしょうか? この値は本当に1から1.2の間ですか?
vertical-align
は
line-height
どのように影響しますか?
それほど単純ではないCSSメカニズムを掘り下げましょう...
フォントサイズについて話を始めましょう。
それぞれが独自の
font-family
持つ3つの
span
要素を含む
p
タグを持つこの単純なHTMLを考えてください:
<p> <span class="a">Ba</span> <span class="b">Ba</span> <span class="c">Ba</span> </p>
p { font-size: 100px } .a { font-family: Helvetica } .b { font-family: Gruppo } .c { font-family: Catamaran }
異なるヘッドセットで同じ
font-size
を使用する場合、高さは異なります。
この機能について知っていても、なぜ
font-size: 100px
要素を作成しないの
font-size: 100px
か? これらの値を測定しました:Helvetica-115px、Gruppo-97px、Catamaran-164px。
一見奇妙に見えますが、すべてが期待されています-その理由はフォント自体にあります。 仕組み:
- フォントは独自のem-square (em-square)(別名UPM、emあたりのユニット-ピンあたりのユニット)-各文字が描画される一種のパッドを設定します。 この正方形では、相対単位が測定に使用され、原則として1000単位のサイズが使用されます。 1024、2048、または異なる数のユニットも発生しますが。
- 相対的な単位の数に応じて、上部と下部の拡張要素(アセンダー/ディセンダー)の高さ、大文字と小文字などのフォントメトリックが設定されます。 一部の値は、emスクエアの範囲を超える場合があります。
- ブラウザでは、相対単位は必要な
font-size
に合わせて拡大縮小されfont-size
。
カタマランフォントを取得してFontForgeで開き、メトリックを取得します。
- em-squareは1000単位と見なされます。
- 上部のリモート要素の高さは1100単位で、下部は540です。
いくつかのチェックの後、Mac OSのブラウザーはHHead Ascent / Descentの値を使用し、Windows-Win Ascent / Descentの値を使用することが判明しました(これらの値は異なる場合があります)。 さらに、大文字の大文字の高さは680単位で、小文字のXの高さは485です。
したがって、カタマランフォントは、1000単位のem正方形で1100 + 540単位を使用するため、font-size:100pxでは、164pxの高さが得られます。 この計算された高さは、要素のコンテンツ領域を決定します (この用語はテキストの後半で使用されます)。 コンテンツ領域は、
background
プロパティが適用される領域であると考えることができます。
大文字の高さは68px(680単位)、小文字(x-height)は49px(485単位)であると仮定することもできます。 その結果、1ex = 49pxおよび1em = 100pxであり、164pxではありません(残念ながら、emは計算された高
font-size
ではなく
font-size
依存します)。
深く潜る前に、遭遇する主なポイントを考慮してください。
p
要素は、画面に表示されるときに、適切な幅の複数の行で構成される場合があります。 各行は1つ以上のインライン要素(HTMLタグまたはテキストコンテンツ用の匿名インライン要素)で構成され、ラインボックスコンテナと呼ばれます。 行コンテナの高さは、その子の高さに依存します。 つまり、ブラウザは各ラインアイテムの高さを計算し、それから-ラインコンテナの高さ(子の最高点から最低点まで)を計算します。 その結果、文字列のコンテナの高さは、常にすべての子を収容するのに十分です(デフォルト)。
各HTML要素は、実際には文字列コンテナのスタックです。 行のすべてのコンテナの高さがわかっている場合、要素の高さもわかります。
上記のHTMLコードを次のように変更する場合:
<p> Good design will be better. <span class="a">Ba</span> <span class="b">Ba</span> <span class="c">Ba</span> We get to make a consequence. </p>
3つの行コンテナが生成されます。
- 最初と最後には、1つの匿名文字列要素(テキストコンテンツ)があります。
- 2番目には、2つの匿名ライン要素と3つの
span
要素があります。
行の2番目のコンテナは、その子の計算されたコンテンツ領域、より正確にはカタマランフォントを使用しているため、他のコンテナよりも高さが大きいことがはっきりとわかります。
文字列コンテナを作成する際の難しい部分は、実際、CSSを介してそれを表示したり操作したりできないことです。 背景を
::first-line
適用しても、行の最初のコンテナの高さを表示するのに役立ちません。
行の高さ:問題およびその他の問題について
ここまで、2つの概念-コンテンツ領域と文字列コンテナを紹介しました。 注意深く読んだ場合、行コンテナの高さはその子の高さに基づいて計算されることに気づきましたが、子のコンテンツ領域の高さに基づいているとは言いませんでした。 これは大きな違いです。
奇妙に見えるかもしれませんが、広告申込情報には2つの異なる高さがあります:コンテンツ領域の高さと仮想領域の高さ (私はこの高さを見ることができないため、「仮想領域」という用語を作成しました。この用語の仕様では、見つかりません)。
- コンテンツ領域の高さは、(前述したように)フォントメトリックによって決まります。
- 仮想領域の
line-height
はline-height
であり、これは行コンテナーの高さを計算するために使用される高さです。
さらに、上記は、
line-height
はベースライン間の距離であるという一般的な信念に反論しています。 CSSでは、これは当てはまりません。
他の編集プログラムでは、これはベースライン間の距離です。 たとえば、WordとPhotoshopではそうです。 主な違いは、CSSではこの距離が最初の行の距離であることです。
仮想領域とコンテンツ領域の計算された高さの差は、リーディングと呼ばれます。 先頭の半分がコンテンツ領域の上部に追加され、2番目が下部に追加されます。 したがって、コンテンツ領域は常に仮想領域の中央に配置されます。
計算された値に応じて、
line-height
(仮想領域)は、コンテンツ領域と同じか、大きいか、または小さい場合があります。 仮想領域が小さい場合、先頭の値は負であり、ラインコンテナの高さはその子よりも視覚的に小さくなります。
他の種類の小文字要素があります:
- 置換可能なインライン要素(
img
、input
、svg
など); -
inline-block
およびinline-*
型のすべての要素。 - 特定の書式設定コンテキストに関係するインライン要素(たとえば、flexbox要素では、すべてのflexコンポーネントがロックされます)。
このような特別な広告申込情報の場合、高さは、
height
、
margin
border
プロパティに基づいて計算
height
れます。
height
auto
指定されている場合、
line-height
が適用され、コンテンツ領域の
line-height
は
line-height
ます。
それでも、問題は同じままです:
line-height
通常の値は何ですか? コンテンツ領域を計算する場合のように、この質問に対する答えは、フォントメトリックの中に見つける必要があります。 FontForgeに戻ります。 カタマランのemスクエアサイズは1000ですが、上部と下部の拡張要素には多くの値があります。
- アセント/ディセントの一般的な値:上部の拡張の高さは770、下部は230です。キャラクターの作成に使用します(テーブル "OS / 2")。
- アセント/ディセントメトリック:上部の詳細の高さは1100、下部は540です。コンテンツ領域の高さを決定するために使用されます(テーブル「hhea」および「OS / 2」)。
- ラインギャップメトリック(ライン間隔)。
line-height: normal
を決定するために使用され、この値はAscent / Descentメトリックに追加されます(表「hhea」)。
この場合、カタマランフォントは、行間隔が0単位であると判断します。したがって、
line-height: normal
は、コンテンツ領域(1640単位、つまり1.64)と等しくなります。
比較として:Arialフォントの場合、em-squareは2048単位、上部の詳細の高さは1854、下部は434、行間隔は67です。したがって、
font-size: 100px
、コンテンツ領域は112px(1117単位)で、値は
line-height: norma
通常-115px(1150単位または1.15)。 これらのメトリックはすべて、フォントごとに個別であり、フォント設計者によって設定されます。
したがって、
line-height: 1
設定
line-height: 1
非効率的です。 無次元の値はコンテンツ領域ではなく
font-size
依存し、コンテンツ領域のサイズが仮想領域のサイズを超えるという事実が多くの問題の原因であることを思い出させてください。
しかし、理由は
line-height: 1
だけではありません。 さらに言えば、コンピューターにインストールされた1117個のフォント(はい、Google Web Fontsのすべてのフォントをインストールしました)、1059個のフォント、つまり95%のうち、計算された
line-height
インジケーターは1より大きいです。
line-height
範囲は0.618〜3.378です。 (あなたには見えなかった-3.378!)
line-box
計算に関する小さな詳細:
- インライン要素の場合、パディングと境界線によって背景領域が増加しますが、コンテンツ領域の高さは増加しません(ラインコンテナの高さも増加しません)。 したがって、コンテンツ領域は常に画面に表示されるものではありません。
margin-top
およびmargin-bottom
は影響がありません。 - 置換可能な
inline-block
要素、inline-block
要素、およびロックされたinline-block
要素padding
、margin
、およびborder
は、height
を増加height
せるため、コンテンツ領域および行のコンテナーの高さが増加します。
vertical-align:すべてを制御するプロパティ
行コンテナーの高さを計算する主な要因ですが、垂直方向の配置プロパティについてはまだ詳しく説明していません。 さらに、文字列の書式設定コンテキストでは、
vertical-align
が主要な役割を果たしていると言えます。
デフォルト値は
baseline
です。 上部および下部の詳細の高さ(アセンダー/ディセンダー)などのフォントメトリックを覚えていますか? これらの値は、ベースラインがどこにあるか、したがって、上部と下部の比率を決定します。 上部と下部の拡張要素の比率が50/50になることはめったにないため、たとえば同じレベルの要素で予期しない結果が生じる可能性があります。
このコードから始めましょう:
<p> <span>Ba</span> <span>Ba</span> </p>
p { font-family: Catamaran; font-size: 100px; line-height: 200px; }
font-family
、
font-size
、およびfixed
line-height
継承する2つの兄弟
span
要素を持つ
p
タグ。 ベースラインは同じであり、行コンテナーの高さは
line-height
等しくなります。
しかし、2番目の要素の
font-size
が小さい場合はどうでしょうか?
span:last-child { font-size: 50px; }
どんなに奇妙に聞こえても、デフォルトのベースラインを揃えると、下の図に示すように、行コンテナの高さ(!)が増加する可能性があります。 行コンテナの高さは、その子の最高点から最低点まで計算されることを思い出してください。
これは無次元の
line-height
値を支持する議論になる可能性がありますが、完全な垂直リズムを作成するには固定値が必要な場合があります。 正直なところ、あなたが何を選んだとしても、常にラインを揃えるのに問題があります。
別の例を考えてみましょう。
line-height: 200px
持つ
p
タグ
line-height: 200px
継承する単一の
span
を含む
line-height: 200px
<p> <span>Ba</span> </p>
p { line-height: 200px; } span { font-family: Catamaran; font-size: 100px; }
行コンテナの高さは何ですか? 200pxと仮定できますが、そうではありません。 問題は、
p
が独自の異なる
font-family
値を持っていること
font-family
(デフォルトはserifです)。
p
タグと
span
タグのベースラインは高さが異なる可能性が高いため、ラインコンテナーの高さは予想よりも大きくなります。 これは、ブラウザが文字列の各コンテナがゼロ幅文字で始まると仮定して計算を実行するためです。これは、仕様では「ストラット」と呼ばれます。
目に見える効果を持つ目に見えないシンボル。
ですから、兄弟の場合と同じ問題がまだあります。
ベースライン上のアライメントでは、すべてが悪いですが、多分
vertical-align: middle
は私たちを救うでしょうか? 仕様に記載されているように、
middle
は、「親コンテナのベースラインにプライマリ要素のx-heightの半分を加えた垂直な中点にコンテナを揃えます。」 ベースラインとx高さ(x高さ)の比率は異なる可能性があるため、
middle
との位置合わせに依存することもできません。 そして最悪なのは、ほとんどのシナリオで、
middle
真に「中心」になること
middle
ないという事実です。 これは、CSSで設定できない要素が多すぎる(x-height、上下の詳細要素の比率など)の影響を受けます。
これに加えて、場合によっては有用であることが判明する可能性のある他の4つの値があります。
-
vertical-align: top / bottom
行コンテナの上部または下部の境界線の配置。 -
vertical-align: text-top / text-bottom
コンテンツ領域の上部または下部の境界線の配置。
ただし、注意してください。すべての場合において、仮想領域、つまり、目に見えない高さが揃えられます。
vertical-align: top
を使用した簡単な例を考えてみましょう。 目に見えない
line-height
は、奇妙ではあるが期待される結果をもたらします。
最後に、
vertical-align
は、コンテナをベースラインに対して上下に移動する数値も受け入れます。 この最後のオプションは便利かもしれません。
CSSはすごい
line-height
と
vertical-align
の相互作用について説明しましたが、問題は、CSSを介してフォントメトリックを制御できるかどうかです。 要するに、いいえ。 本当に欲しいのですが。 いずれにせよ、私はそれはいくつかの楽しみを持っている時間だと思う。 フォントメトリックは定数値であるため、少なくとも何かがうまくいくはずです。
たとえば、正確に100pxの大文字のカタマランフォントのテキストが必要な場合はどうなりますか? 実行可能だと思われるので、計算してみましょう。
まず、すべてのフォントメトリックをカスタムCSSプロパティとして指定し、大文字の高さが100pxになる
font-size
を計算します。
p { /* */ --font: Catamaran; --fm-capitalHeight: 0.68; --fm-descender: 0.54; --fm-ascender: 1.1; --fm-linegap: 0; /* */ --capital-height: 100; /* font-family */ font-family: var(--font); /* , */ --computedFontSize: (var(--capital-height) / var(--fm-capitalHeight)); font-size: calc(var(--computedFontSize) * 1px); }
かなり簡単ですね。 しかし、テキストを視覚的に中央に配置し、残りのスペースを文字「B」の上下に均等に配置する必要がある場合はどうでしょうか。 これを行うには、上下の拡張要素の比率に基づいて
vertical-align
を計算する必要があります。
最初に、
line-height: normal
とコンテンツ領域の高さを計算します:
p { … --lineheightNormal: (var(--fm-ascender) + var(--fm-descender) + var(--fm-linegap)); --contentArea: (var(--lineheightNormal) * var(--computedFontSize)); }
次に必要なもの:
- 大文字の下端から下端までの距離。
- 大文字の上端から上端までの距離。
このようなもの:
p { … --distanceBottom: (var(--fm-descender)); --distanceTop: (var(--fm-ascender) - var(--fm-capitalHeight)); }
これで、これらの距離の差に、計算された
font-size
値を掛けた値として
vertical-align
を計算できます(この値は小文字の子に適用する必要があります)。
p { … --valign: ((var(--distanceBottom) - var(--distanceTop)) * var(--computedFontSize)); } span { vertical-align: calc(var(--valign) * -1px); }
最後に、必要な
line-height
値を設定し、垂直方向の配置を維持しながら計算します。
p { … /* */ --line-height: 3; line-height: calc(((var(--line-height) * var(--capital-height)) - var(--valign)) * 1px); }
文字「B」と同じ高さのグラフィック要素を追加するのは非常に簡単です。
span::before { content: ''; display: inline-block; width: calc(1px * var(--capital-height)); height: calc(1px * var(--capital-height)); margin-right: 10px; background: url('https://cdn.pbrd.co/images/yBAKn5bbv.png'); background-size: cover; }
このテストはデモンストレーションのためにのみ示されているものであり、その結果に頼るべきではないことを思い出させてください。 多くの理由があります。
- フォントメトリックに一貫性がない場合、ブラウザでの計算は一定ではありません。 ¯(ツ)/¯
- フォントがロードされなかった場合、バックアップフォントメトリックが異なる可能性が高く、多くの値をすばやく処理することができなくなります。
まとめると
作業例:
私たちが見つけたもの:
- インラインの書式設定コンテキストを理解するのは本当に難しいです。
- すべての小文字要素には2つの高さがあります。
- コンテンツ領域の高さ(フォントメトリックに依存);
- 仮想エリアの高さ(
line-height
); - それらのどれも確実に視覚化することはできません(開発ツールに携わっており、この欠陥を修正することを決めていない限り、それは素晴らしいことです)。
-
line-height: normal
は、フォントメトリックに依存します。 -
line-height: n
仮想領域はコンテンツ領域より小さくなる場合があります。 -
vertical-align
あまり依存しないでください。 - 行コンテナの高さは、子の
line-height
プロパティとvertical-align
プロパティを使用して計算vertical-align
ます。 - CSSを使用してフォントメトリックを取得または設定することはできません。
しかし、私はまだCSSが大好きです:)
便利なリンク
- フォントメトリック: FontForge 、 opentype.js
- 行の高さを計算します:通常およびブラウザの一部の比率 。
- Ahemは、その仕組みを理解するための特別なフォントです。
- 文字列フォーマットのコンテキストのより深い形式的な説明
- 垂直方向の位置合わせの今後の仕様: Line Gridモジュール
- フォントメトリック、 APIレベル1 、興味深いアイデアのコレクション(Houdini)