納豆、Web、雑記など

vertical-align 考察(よく分からない vertical-align を、いろいろ試して理解する。)

CSS の中で、わたしが混乱してしまうのが vertical-align です。

vertical-align て特殊ですよね? なんか思うように縦方向が揃わなかったり、機能しなかったりします。

なんやねんと思い、一度いろいろ実験したろと思っていたのですが、今回ようやくやってみました。

まあ知っている方や詳しい方には目新しい情報など無い記事ですので、その場合はそっと戻るボタンを押して下さい(笑)

スポンサーリンク

vertical-align には、合わせる対象となるものが必要

vertical-align は「垂直(vertical)」の位置を「合わせる(align)」プロパティです。なので合わせるために2つの要素が必要です

単に vertical-align を指定しただけでは位置が変わらないことがあります。子要素を持つテーブルセル要素(display:table-cell)か、ラインボックス(行ボックス、テキスト)の中にあるインライン要素でなければ機能しません。

HTML
<div><span>table-cell</span></div>
<div><span>テキストなし</span></div>
<div><span>line-height:1</span> line-height:1.5</div>
<div><span>line-height:2</span> line-height:1.5</div>
<div><span>line-height:3</span> line-height:1.5</div>
CSS
div {
  background: rgba( 0, 0, 255, 0.5 );
  height: 2em;
  line-height: 1.5;
  margin: 0.5em 0;
  width: 12em;
}
span {
  background: rgba( 255, 255, 0, 0.5 );
  display: inline-block;
}
div:nth-child( 1 ) {
  display: table-cell;
  vertical-align: bottom;
}
div:nth-child( n + 2 ) > span {
  vertical-align: bottom;
}
div:nth-child( 3 ) > span {
  line-height: 1;
}
div:nth-child( 4 ) > span {
  line-height: 2;
}
div:nth-child( 5 ) > span {
  line-height: 3;
}
表示結果
vertical-align テスト結果1

また、テーブルセル要素での指定とインライン要素での指定では、その仕組みや指定できる種類に若干の違いがあります

テーブルセル要素は、親要素であるテーブルセル要素に vertical-align を設定します。これにより親要素であるテーブルセル要素の下部や中間といった垂位置向に、中の要素(子要素)の位置を揃えて合わせます。

vertical-align テスト結果2

ちなみに、テーブルセル要素の初期値でもあるvertical-align:baselineは少々特殊で、複数のテーブルセル要素が並んだ行の中で、その中のテキストで最も低いベースラインで揃えます。

vertical-align テスト結果3

このことに関しては、こちらの記事が非常に分かりやすく参考になります。わたしも参考にしました。

参考リンク:テーブルセルの vertical-align: baseline · terkel.jp

対してインライン要素では、合わせる自分自身に vertical-align を設定します。こちらはテーブルセルとは違い、インライン要素のテキストと、その親に含まれているテキストとの垂直位置を揃えて合わせます

先ほどのテーブルセル要素でのvertical-align:baselineの挙動はこちらに近いですね。

vertical-align テスト結果4

こちらも他のサイトで詳しく解説されていますので、そちらもご参考にしてください。

参考リンク:

このように違いがあるためか、指定する値もテーブルセル用とインラインレベル用では違いがあります。

このように、同じ vertical-align なのに若干違いがあることが、混乱する原因のような気がします

値に数値を指定できるが、パーセント値指定がline-height基準

vertical-align に指定できる値は、top や middle といったキーワード値から、pxや em といった数値を指定できます。

数値が 0 のときは baseline と同じ位置になります。そして数値指定はそこを基準として位置を数値分、上下に移動させます

実は、この数値にはパーセント値も指定できるのですが、これがちょっとハマります。

パーセント値ですので何かの相対値なのですが、この基準とする対象を単純に考えたらフォントサイズか親相当の行の高さ(ラインボックス)かと思います。

ですが違ってて、実は下の画像のように自身の行の高さ(line-height) が基準になっています。

vertical-align テスト結果5
背景が緑色の line-height は 1.5

まぁ、この場合は気づけばどってことないのですが、知らなかったらいくら調整しても上手くいきません。そりゃそうですよね、基準となる対象を勘違いしているのですから。

和文でフォントの真ん中が難しい(middleが真ん中という訳ではない)

この vertical-align を使う場面として、挿入した画像やアイコンを真ん中に揃える時に使うこともあると思います。

この時、単純に vertical-align に middle(中間という意味)を指定すれば、英文ならばちょど良い位置に揃えてくれます。

ですが、和文では話が変わります。ちょっとズレているように見えるのです。

サンプルとして、まず中心が分かりやすいアイコンのようなものをCSSで作りました。

それを次のようにテキストの前に配置します。

HTML
<div> xテスト(指定なし)</div>
<div> xテスト(middle)</div>
CSS
div {
    background: linear-gradient(
                  rgba( 0, 0, 255, 0.2 ) 25%,
          rgba( 0, 0, 255, 0.4 ) 25%,
                  rgba( 0, 0, 255, 0.4 ) 50%,
                  rgba( 0, 0, 255, 0.6 ) 50%,
                  rgba( 0, 0, 255, 0.6 ) 75%,
                  rgba( 0, 0, 255, 0.2 ) 75%
                );
    height: 2em;
    line-height: 2;
    margin: 0.5em 0;
}
div::before {
    border-bottom-color: #f00;
    border-top-color: #f00;
    border: 0.5em solid #fff;
    content: "";
    display: inline-block;
    height: 0;
    opacity: 0.5;
    width: 0;
}
div:nth-child( 2 )::before {
    vertical-align: middle;
}

これらを表示させたものが、こちらの画像です。

vertical-align テスト結果6

背景色は四色に別れています。line-height が2なので、ちょうど行とフォントと行間の余白、それとフォントの真ん中のラインを見分けやすくしています。

これを見ての通り、中心から少しズレています

なぜズレるかと言えば、本来 middle は「小文字の" x "」の中間の交差点の位置を middle としています。

欧文ではこの「小文字の" x "」が基準点になっているため、この中心を「中間」としても文章全体に違和感は生じません。

ですが平仮名や漢字といった和文の場合、だいたいは正方形の枠に収まるように書きます。つまり字の中心が違うのです

さらに言えば、フォントのデザインによってもこれらは変わってきます。先ほどの画像はズレが分かりやすい「Noto Sans CJK JP」なのですが、それとは違うフォントを指定したところアイコンの位置が変わっています。

vertical-align テスト結果7
左が baseline で、右が middle 。

もうこうなってきたら、どの和文フォントでも共通する正確な中間ラインの取り方なんて不可能だと思います

でも、まあ、中間に近ければ「真ん中だ」と目が勝手に錯覚してくれますので、だいたい真ん中に近ければよいかな~と思っています(笑)

それで設定方法なのですが、やり方自体はいろいろあるのですが結局は vertical-align に相対値である em を指定するのが1番良いように感じます

例えば、先ほどの三種類のフォントで設定してみたところ、次のような感じです。

div:before {
    vertical-align: -0.1em;
}
表示結果
vertical-align テスト結果8

数値はアイコンや画像の大きさによって変わりますが、em の場合フォントの大きさが変わってもアイコンの位置のズレがあまりありません。

まとめ

テストの結果は以上です。

今回いろいろ試してみて vertical-align がどんなものかというのが、何となく分かったような気がします。

位置の違い、とくに真ん中配置とかは非常に細かいことなんですけど、迷う時には迷ってしまうと思うのですよ、わたしのように。

そんな方に対して、この記事が何かの参考になれば、とても嬉しい限りです。

スポンサーリンク