CSSのイマージョン:フォントメトリック、行の高さ、垂直方向の配置

画像



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。



画像



一見奇妙に見えますが、すべてが期待されています-その理由はフォント自体にあります。 仕組み:





カタマランフォントを取得してFontForgeで開き、メトリックを取得します。





いくつかのチェックの後、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つの行コンテナが生成されます。





画像



行の2番目のコンテナは、その子の計算されたコンテンツ領域、より正確にはカタマランフォントを使用しているため、他のコンテナよりも高さが大きいことがはっきりとわかります。



文字列コンテナを作成する際の難しい部分は、実際、CSSを介してそれを表示したり操作したりできないことです。 背景を::first-line



適用しても、行の最初のコンテナの高さを表示するのに役立ちません。



行の高さ:問題およびその他の問題について



ここまで、2つの概念-コンテンツ領域と文字列コンテナを紹介しました。 注意深く読んだ場合、行コンテナの高さはその子の高さに基づいて計算されることに気づきましたが、子のコンテンツ領域の高さに基づいているとは言いませんでした。 これは大きな違いです。



奇妙に見えるかもしれませんが、広告申込情報には2つの異なる高さがあります:コンテンツ領域の高さと仮想領域の高さ (私はこの高さを見ることができないため、「仮想領域」という用語を作成しました。この用語の仕様では、見つかりません)。





画像



さらに、上記は、 line-height



はベースライン間の距離であるという一般的な信念に反論しています。 CSSでは、これは当てはまりません。



画像



他の編集プログラムでは、これはベースライン間の距離です。 たとえば、WordとPhotoshopではそうです。 主な違いは、CSSではこの距離が最初の行の距離であることです。



仮想領域とコンテンツ領域の計算された高さの差は、リーディングと呼ばれます。 先頭の半分がコンテンツ領域の上部に追加され、2番目が下部に追加されます。 したがって、コンテンツ領域は常に仮想領域の中央に配置されます。



計算された値に応じて、 line-height



(仮想領域)は、コンテンツ領域と同じか、大きいか、または小さい場合があります。 仮想領域が小さい場合、先頭の値は負であり、ラインコンテナの高さはその子よりも視覚的に小さくなります。



他の種類の小文字要素があります:





このような特別な広告申込情報の場合、高さは、 height



margin



border



プロパティに基づいて計算height



れます。 height



auto



指定されている場合、 line-height



が適用され、コンテンツ領域のline-height



line-height



ます。



画像



それでも、問題は同じままです: line-height



通常の値は何ですか? コンテンツ領域を計算する場合のように、この質問に対する答えは、フォントメトリックの中に見つける必要があります。 FontForgeに戻ります。 カタマランのemスクエアサイズは1000ですが、上部と下部の拡張要素には多くの値があります。





この場合、カタマランフォントは、行間隔が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



計算に関する小さな詳細:





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



を使用した簡単な例を考えてみましょう。 目に見えない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; }
      
      





画像



このテストはデモンストレーションのためにのみ示されているものであり、その結果に頼るべきではないことを思い出させてください。 多くの理由があります。







まとめると



作業例:





私たちが見つけたもの:





しかし、私はまだCSSが大好きです:)



便利なリンク






All Articles