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

カテゴリ: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

コメント

1 - hide さん

いつも参考にさせて頂いています。

#(センタリング名)
内のpaddingがtopとleft以外おかしくなるのはなぜでしょうか?

padiingを4方向指定してもrightとbottomがズレます。

因みに、popupFooterも入っています。

宜しければアドバイス下さいませ。

2010年9月11日 12:39

2 - hide さん

連投ですみません。
解決しました。

#blockCnteringのwidth値は、画像のwidth値からpadding分減らすんですね。
padding: 20pxなら-40px。

自前の画像で、そのままwidth指定していたのが原因でした。orz

2010年9月11日 16:19

3 - えど Author Profile Pageさん

>>hideさん
コメントありがとうございます!
解決されたようでよかったです。
なにかあればまたコメントください!

2010年9月11日 17:21

4 - shin さん

はじめまして、今回制作にあたって、コンテンツエリアを中央配置してほしいと、要望がり、
参考にさせて頂きました。

一つご質問なんですが、Firefoxでは問題無く中央配置されたんですが、safariで確認したところ、
上下が中央配置されず、一番上に配置されてしまいます。

safari用にハックをしないとだめでしょうか?

すいませんが、アドバイスの方、宜しくお願い致します。

2010年12月20日 10:02

5 - えど Author Profile Pageさん

>>shinさん
コメントありがとうございます。
基本的にブラウザは限定していないのですが、
サンプルを見ても上に表示されていますでしょうか?

もし実装されたサイトだけ上に表示されている、ということであれば
もしかしたら他で指定されているスタイルがなにか影響してしまっているのかもしれません。

CSSはそうした別のところで定義されたものが影響することが多くあるので、
一度そのあたりを確認してみてもらえますか?

また、指定をセンタリングのもののみにしたりなど、
徐々にスタイルの適用範囲を広げていくとどこに問題があるか分かりやすいと思います。

2010年12月26日 14:31

6 - masa さん

はじめまして、masaと申します。いつも大変参考になる情報ありがとうございます。
とても助かっております。

IE6、7でボックスの幅よりウインドウサイズを縮め他時ですが、
inline-block表示にしたspan要素がボックス要素と縦に並んでしまうため、
レイアウトが崩れてしまうようです。

いろいろ試してみたところ、body要素に対して
width: 504px;
margin-left:auto;
margin-right:auto;
の指定を追加すると、ウィンドウが狭くなってもうまく表示されるようです。
(幅を合わせるため、span内の も削除し、空にしました。)
ただ、これだと、widthが固定になってしまうので幅、高さ共に可変
のスタイルを指定したいときができないですね。

2011年2月23日 01:56

コメントを投稿





承認されるまでコメントは表示されません。しばらくお待まちください。