更新 : 2006年07月01日

CSSでfloatを指定したボックスを含むボックスの背景が出なくなる件

「CSSで段組したらFirefoxで背景が出ねーよっ」て話をよく聞くので色々試してみました。

コンテンツメニュー
  1. 元になるHTML
  2. 特に何も考えずfloatを使った場合
  3. 外のボックスに幅を与えてみる
  4. 一般的な解決方法
  5. その他の解決方法 overflowを使う
  6. 最終回答
  7. 番外編
  8. 更新履歴
  9. このドキュメントについて

元になるHTML

    <div id="container">
        <div class="leftBox">内容</div>
        <div class="rightBox">内容</div>
    </div>
例1(ブログ)
class="leftBox"のボックスの内容は「サイドバー」。class="rightBox"の内容は「記事部分」。
例2(ウェブサイト)
class="leftBox"のボックスの内容は「ローカルナビゲーション」。class="rightBox"の内容は「情報」。
例3(画像)
class="leftBox"、class="rightBox"ともに画像でfloatを使って並べている。
ターゲットブラウザ
  • Internet Explorer 5.0 ~
  • Firefox 1.x ~
  • Netscape 6.0 ~
  • Opera 6.0 ~
  • Safari 1.x ~
  • Mac Internet Explorer 5.x

※ 以下に登場するIEとはWindows Internet Explorer 6.0 後方互換モードを示しています。
Mac版Internet ExplorerはMacIEとして明示します。

特に何も考えずfloatを使った場合

左にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.leftBox {
    width: 45%;
    float: left;
    border: 2px solid #000000;
}

右にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.rightBox {
    width: 45%;
    float: right;
    border: 2px solid #000000;
}

一番外側のボックスには以下のようなスタイルが記述されています。

#containerA {
    color: #000000;
    background-color: #B4D543;
    border: 2px solid #F1288B;
    padding-top: 20px;
    padding-bottom: 20px;
}

そもそもfloatはボックスを"浮かせる"ものなので、内側のボックスが全部浮かんでしまった場合、外側のボックスの高さはなくなってしまいます。
上記のスタイルの場合、IEやFirefox、Operaではpadding分の背景(緑色)とボーダー(ピンク色)しか表示されません。
これは、ブラウザのバグではなく、正しい挙動です。

外のボックスに幅を与えてみる

左にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.leftBox {
    width: 45%;
    float: left;
    border: 2px solid #000000;
}

右にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.rightBox {
    width: 45%;
    float: right;
    border: 2px solid #000000;
}

一番外側のボックスには以下のようなスタイルが記述されています。

#containerB {
    color: #000000;
    background-color: #B4D543;
    border: 2px solid #F1288B;
    padding-top: 20px;
    padding-bottom: 20px;
    width: 90%;
}

幅を与えてみると、不思議なものでIE(IE6、IE7 beta)で背景(緑)が内容のボックスの高さに合わせて現れます。
この挙動はIEのバグで、Firefox、Operaなどでは依然背景は一部しか出ません。
ここで、よく聞く「IEでは背景出るのにFirefoxで見たら背景出ない」という現象が起きているわけです。

一般的な解決方法

※ 一般的な解決方法ですが、最終的には問題があります。

左にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.leftBox {
    width: 45%;
    float: left;
    border: 2px solid #000000;
}

右にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.rightBox {
    width: 45%;
    float: right;
    border: 2px solid #000000;
}

一番外側のボックスには以下のようなスタイルが記述されています。

#containerC {
    color: #000000;
    background-color: #B4D543;
    border: 2px solid #F1288B;
    padding-top: 20px;
    padding-bottom: 20px;
    min-height: 1em;
    display: inline-table;
}

#containerC:after {
    content: "";
    display: block;
    clear: both;
    height: 1px;
    overflow: hidden;
}

/*\*/
* html #containerC {
    height: 1em;
}

#containerC {
    display: block;
}
/**/

モダンブラウザ対策

#containerC:aftercontentを指定すると、ボックスの中の一番最後に新たなテキストや画像を挿入することができます。
挿入したものをブロック要素化し"clear: both"をかけることによってボックス内のfloatをすべて解除することができます。
すると、floatしているボックスの高さに応じて外側のボックスの高さが拡張されるようになります。

しかし現在、擬似要素":after"と"content"が解釈できるブラウザはFirefox、Opera、Safariなどのモダンブラウザのみです。
IE6.0は理解できませんし、次期バージョンIE7.0でもサポートされるかどうかは怪しいです(現時点でリリースされているIE7 beta2でもサポートされていません)。

WinIE5.0~6.0対策

下記の部分の解説

* html #containerC {
    height: 1em;
}

バックスラッシュハックと、スターハックを用いてWinIE5.0~6.0のみ指定を有効にする方法を使っています。
WinIE5.0~6.0には外側のボックスに高さ(値は何でもよい)を与えると、内側のボックスのフロートに関わらずボックス高さを拡張してしまうバグ(仕様?)があります。
それを利用して、背景を表示させるようにしています。
このハックはIE7では理解できません。 なぜ、WinIE5.0~6.0のみに指定するかというと、FirefoxやOperaなど正しくCSSを理解できるブラウザでは指定した高さ(上記では1em)の影響が出てしまうためです。

IE7対策

一点注意しなければならないのは、#containerCに記述されている"min-height: 1em"の記述です。 これはボックスの最小高さを指定するもので、現在リリースされているモダンブラウザでサポートされています(IE6は含まれません)。
この指定を入れることでIE7で外側のボックスの高さをフロートした内側のボックスの高さに合わせて拡張することができます。
"1em"の高さ自体は1pxでも1%でもなんでもよいと思います。

min-height以外にも上で書いたように、"width: XXpx"を外側のボックスに指定することで高さが拡張され背景色が表示されることを確認しました。
しかしながら、毎度幅指定ができるわけではありません。例えばリキッドレイアウトで、ボックスの幅は%指定、左右の余白(padding)がpx指定の場合です。

min-heightでボックスの最小高さを指定することで他のブラウザで影響はないはずです(内容物が1emより小さい場合は最小高さを変える必要はあります)。

※ この方法は飽くまで現在プレビュー版としてリリースされているIE7 betaで有効になるというだけで、正式版で有効になるかどうかはリリースされてみるまでは分かりません。

MacIE対策

display: inline-tableと記述することで、MacIEでも外側のボックスの高さを内容にあわせて拡張することができます。
display: inline-tableの記述をそのままににしておくのも気持ち悪いのでバックスラッシュハックでMacIE以外のブラウザでdisplay: blockになるように指定してあります。

問題点

display: inline-tableをCSSに記述するとFirefoxのJavaScriptコンソールが以下のようなエラーを吐き出します。

エラー: 'display' プロパティの値をパース中にエラーが発生しました。 このスタイル宣言は無視されました。

無視されているのなら問題ないのですが、非常に気持ち悪いです。
またJavaScriptでobject.style.displayの値を切り替えたりするときに、ブラウザ振り分けなどの面倒な事態が発生することが予想されます。

また、確かではありませんがMacIEにおいてdisplay: inline-tableが効いているボックスの子要素を絶対配置(position: absolute)で配置しようとしても、意図とは反した場所に表示されてしまう現象を何度か経験したことがあります。(手元にMacが無いのでどういった場合に起きるか確認できていません)

その他の解決方法 overflowを使う

他にもoverflowを使う方法もあります。

また、その方法には問題もあるそうです

問題の内容としては、

overflow:scroll ではスクロールバーが出てしまいます。また、overflow:hidden では Netscape7.1 で内容が表示されない(バグ)、overflow:auto ではMacIE5 でスクロールバーが出るようです。

とういことだそうで、実際にNetscape7.1で表示させてみたら、見事に表示されませんでした。片方を立てればもう一方が立たず。最新のNetscape日本語版が7.1であることを考えるとかなり致命的であることは言うまでもありません。

また、overflowをMacIEで使う際、注意点があります。

最終回答

一般的な解決方法」「その他の解決方法 overflowを使う」でいくつか問題点がわかりました。

これらの方法の問題を踏まえ、応用してみると

左にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.leftBox {
    width: 45%;
    float: left;
    border: 2px solid #000000;
}

右にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.rightBox {
    width: 45%;
    float: right;
    border: 2px solid #000000;
}

CSSの記述は以下のようになります。

#containerD {
    color: #000000;
    background-color: #B4D543;
    border: 2px solid #F1288B;
    padding-top: 20px;
    padding-bottom: 20px;
    overflow: hidden;
}

#containerD:after {
    content: "";
    display: block;
    clear: both;
    height: 1px;
    overflow: hidden;
}

/*\*/
* html #containerD {
    height: 1em;
    overflow: visible;
}
/**/

ここで使用しているoverflow: hidden;はMacIEで背景色を表示させるための記述です。これで、displayの値はblockのままとなりJavaScriptでのobject.style.displayを操作する場合も問題なくなります。
WinIE用に高さが指定してあり、そのままだと高さ1emより溢れる内容が隠れてしまうので、バックスラッシュハックでoverflow: visibleを指定してあります。
更に"#containerD:after"を記述することによってNN7でも問題なく表示されるようになりました。

CSSによる段組(マルチカラム)レイアウト講座 - 基礎編5 フロートの性質から引用

簡単に言うと、height の値が auto で overflow の値が visible 以外のブロック要素が、そのマージン下辺よりも下にくるようなフロートを子に持つならば、その高さはフロートを含むように広げられる、すなわち、フロートの親ボックスが高さの算出時に子のフロートを含めないのは、親ボックスの overflow の値が visible のときに限るのです。

とのことなので、overflow: hiddenを使用すると外側のボックスの高さがフロートした内側のボックスの高さによって拡張するのはバグでもなんでもなくて仕様のようです。
ゆえに、IE7 betaでも問題なく表示されます。

あれこれCSSソースを書いていますが実際必要な部分は下記のソースとなります。

#container {
    overflow: hidden;
}

#container:after {
    content: "";
    display: block;
    clear: both;
    height: 1px;
    overflow: hidden;
}

/*\*/
* html #container {
    height: 1em;
    overflow: visible;
}
/**/

以上が今回の調べで分かった「CSSで段組したらFirefoxで背景が出ねーよっ」への最終回答となります。

番外編(お勧めではないですけど)

実はややこしい方法をせずとも、背景を表示させる方法はあります。
HTMLソースは以下のようになります。

    <div id="box">
        <div id="containerE">
            <div class="leftBox">内容</div>
            <div class="rightBox">内容</div>
        </div>
    </div>

左にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.leftBox {
    width: 45%;
    float: left;
    border: 2px solid #000000;
}

右にフロートするボックス

このボックスには以下のようなスタイルが適用されています

.rightBox {
    width: 45%;
    float: right;
    border: 2px solid #000000;
}

CSSは以下のような記述となります

#containerE {
    color: #000000;
    background-color: #B4D543;
    border: 2px solid #F1288B;
    padding-top: 20px;
    padding-bottom: 20px;
    float: left;
    width: 90%;
}

<div id="containerD">を更に<div id="box">で囲んでcontainerDをフロートさせると、不思議なことにcontainerDに指定した背景色が表示されるようになります。

※ Netscape6.0でレイアウトが著しく崩れます。

背景色を表示させるためだけに<div id="box">を追加しているので、お勧めではありません。
他にも<br style="clear:both" />をcontainerD内に挿入する方法もありますが同じく見栄えのための要素追加なので、お勧めではありません。

そもそも<div>で囲むこと自体「見栄え用」じゃないのか?と思いますが、要素(h1とかpとか)を括る箱として使っていれば、あながち意味の無い要素というわけではないと勝手に解釈してします。

更新履歴

2006年07月01日
#container:afterheight: 0pxを与えてもNetscape 7.xで内容物が表示されなくなる場合があったので、height: 1pxに修正。
2006年06月28日
親ボックスにdisplay: inline-tableを与えると内側の子要素の絶対配置がうまくいかない現象を追加。(未検証)

このドキュメントについて

このドキュメントはFsiki管理人 Fsikiがウェブ上から得た情報と実作業で得た経験から極私的にまとめたものです。
内容に誤りなどがあるかもしれませんので、見つけられた場合はこのドキュメントの編集後記にコメントいただければ幸いです。

ページ先頭へ

Copyright © 2005-2006 - Fsiki