ブロック要素を内容量に応じて自動で上下左右にセンタリングさせるトリック

カテゴリ:CSSテクニック 2009年6月 7日 15:37

ブロック要素を内容量に応じて自動で上下左右にセンタリングさせるトリック サンプル画像
このトリックの発案の元になったのはヨモツネットさんの CSS で簡単に上下中央揃えを実現するという記事です。

各所で色々記事が出ていますが(このブログでも 2 回ほど取り上げていますが)、今回は表示するボックスのサイズによらず、(margin などの相殺を使わず)上下左右にボックス要素をセンタリングさせるテクニックの紹介です。

そのため、内容量に応じて高さが変わる状況でも垂直方向へのセンタリングが可能になります。

ブロック要素を上下左右(垂直)にセンタリングさせるトリック デモ

今回のテクニックには、IE6, 7 向けに余分な要素を挿入する必要があります。
IE6, 7 をターゲットとしない場合は、HTML もすっきりと書くことができます。

サンプルダウンロード

ダウンロードされるファイルには、デモで使用しているものがそのまま入っています。
デモのような使い方をしたい場合は、ダウンロードされた style.css 内の#blockCenteringの width, height, padding あたりを修正することでそのまま応用できるかと思います。

▼EntryMore▼

CSS ソース

HTML ソース

このテクニックは、モダンブラウザと IE6, 7 で指定方法が大幅に異なります。
基本的な動作原理は以前の記事の 異なるサイズの画像を縦横中央配置にしてリスト状に並べる で紹介しているテクニックの応用です。

今回のこのテクニックは「準備中」など画面中央に表示したい場合を想定しています。
なので、あるコンテンツ内の要素をセンタリングさせたい、といった場合は html, body と書かれている箇所を適宜置き換えて使用してください。

モダンブラウザ向け CSS の指定

それでは、まずはモダンブラウザのテクニックから見ていきましょう。

ポイントは、html, body をそれぞれtable,table-cellと見立てることです。
というのも、td 要素では上下左右のセンタリングは比較的簡単にできますよね。

これが table なら簡単なのに・・と思う場面も少なくないと思います。
それをまさに、CSS で指定してしまおう、というのが今回のテクニックの肝です。

プロパティの指定は、html 要素には display: tableを、body 要素にはdisplay: table-cellを指定します。

こうすることで、body 要素自体がさも td 要素のように振舞うことになります。
あとは、vertical-align: middleを指定すれば body 要素内のボックスが垂直方向にセンタリングされます。

※注意点として、width, height は html, body 要素ともに 100% にしてください。
table 要素の挙動として明確に幅指定がされていない場合はコンテンツの内容に応じて伸縮してしまうので、100% の指定がないとうまくセンタリングされません。

あとは水平方向にボックスをセンタリングすれば完了です。
水平方向のセンタリングは普段から使用していると思うので簡単ですね。
センタリングさせたいボックスに対してmargin: 0 autoを指定すれば OK です。

IE6, 7 向け CSS の指定

さて、例によって IE6, 7 はdisplay: tableに対応していません。
そのため、display: table 以外の方法で垂直方向のセンタリングを実現します。

HTML ソースを見てもらうと分かりますが、まず body 要素直下に IE6, 7 のみに条件付コメントで<span id="dummy">&nbsp;</span>を読み込ませます。

IE6, 7 向けのテクニックは、インライン要素の場合はvertical-align: middleで要素が垂直方向にセンタリングされることを利用したトリックです。

条件付コメントで読み込んだ span 要素をまずdisplay: inline-blockでインラインブロック要素に変換します。
この inline-block、IE6, 7 の場合インライン要素には仕様通り指定できるのですが、なぜかブロック要素に指定しても無視される、という不思議な仕様があります。

なので span 要素でなくても構いませんが、インライン要素を入れるようにしてください。

さて、インライン要素の場合は vertical-align: middle で要素が垂直方向にセンタリングされる、ということは説明しました。
なので、インライン要素の高さがブラウザ領域いっぱいと同じになり、表示されている内容がすべてインライン要素であるなら、垂直方向にセンタリングできる、ということを意味します。

先の inline-block を挿入した理由はこの「インライン要素の高さがブラウザ領域いっぱい」となるようにするためのトリックです。

inline-block を指定した要素は、インライン要素でありながら高さや幅を持つことができるようになります。
なので、height: 100%を指定すればブラウザ領域いっぱいに高さが確保されます。

続くトリックは、画面の中央に表示したい要素を "inline-block のような状態" にします。
そもそも IE6, 7 はブロック要素には display: inline-block は指定できません。
そこでさらにトリックを使い、"inline-block のような状態" を実現します。

主要プロパティは 2 つ。display: inlinezoom: 1です。
IE6, 7 にはhasLayoutという独自仕様があります。
hasLayout とは、その名の通り "レイアウトを持っているかどうか" を識別するものです。

レイアウトを持っている、とは、width や height などのいわゆるブロック要素のような状態を言います。
通常、インライン要素は width や height が指定できないので hasLayout は false になります。
しかし、この hasLayout を true にする CSS プロパティが存在します。

それがzoom: 1、というわけです。
さてここで、display: inline を指定したことによって画面中央に表示したいブロック要素(サンプルでは #blockCentering)はインライン要素となります。
さらに、zoom: 1 によって "レイアウトを持っている状態" となります。

つまり、インライン要素でありながらブロック要素と同じようにレイアウト情報を持っている、ということになります。これって display: inline-block と同じですよね。

こうして無事、IE6, 7 でも inline-block をブロック要素にも適用することができました。
最後に、#dummy と #blockCentering に対してvertical-align: middleを指定すれば、body 要素直下にはインライン要素のみが存在することになり、さらに vertical-align: middle で要素が垂直方向にセンタリングされる、というわけです。

合わせて読むと役に立つかもなエントリー

この記事のカテゴリー一覧を見る⇒CSSテクニック

  • このエントリーをはてなブックマークに追加

トラックバックURL

http://css-eblog.com/cgi-bin/mt/mt-tb.cgi/143