atsukanrockのブログ

Microsoft系技術を中心にぼちぼち更新します

縦位置を中央揃えにする

はじめに

CSSでブロック要素内のテキストの縦位置を中央揃えにするのは難しい。その理由は、「vertical-alignの使い方」によくまとまっている。簡単に言うと「vertical-alignプロパティがインライン要素とテーブルセルにしか適用できない」ためである。vertical-alignプロパティは、divなどのブロック要素には適用できない。
このため、私が現在開発中のシステムではtableを利用した。おそらくWeb標準に反すると思うが、Web標準に反しない形でこれを実現するのは不可能だと判断した。本エントリでは、なぜ不可能だと判断したのかを記述する。

よく紹介されている実現方法

外枠がdiv、テキストをpで囲むとして

div
{
  height: 5em;
  position: relative;
  width: 10em;
}

p
{
  margin-top: -0.5em;
  position: absolute;
  top: 50%;
}

のようにする。pに適用した3プロパティがポイント。詳しい解説は省略する。

サンプル


ほげほげ

対応できないこと

テキストが何行になるのかが不定な場合、対応できない。

対応できないことのサンプル

上記のサンプルでpの中のテキストが長い場合、


ほげほげほげほげほげ

のようになってしまう。

対応できない理由

margin-topには、テキストが2行になるなら-1emを、3行になるなら-1.5emを設定する必要がある。テキストの長さが不定だと、それがブラウザ上で何行で表示されるかをWebサーバ上で知る方法はない*1ので、この方法では対応できない。

幅の単位をemにすれば対応できるのでは?

ブロック要素の幅の単位をemにすると、テキストの文字数をカウントすることで、テキストが何行で表示されるかを大体予想できる。しかし、それはあくまで「大体」であり、フォントなどに影響を受けるので正確に知ることはできない。

他の実現方法は?

line-heightプロパティを利用する方法があるが、これはテキストが1行の場合にしか対応できない。

ということで

ブロック要素内で、文字数が不定なテキストの縦位置を中央揃えにするには、tableを使うしかない*2

*1:私が知る限り

*2:誰か、良い解決方法があれば教えてください