Single Article

フロートとネガティブマージンまとめ:CSS

tableレイアウトをやってた人も計算してからコーディングしてたと思います。CSSのfloatを使用したレイアウトにしても、floatの挙動を正確に覚えれば、緻密な構成が可能になります。以下は私が覚えたときのフロートレイアウトの考え方のまとめです。

A.フロートの基本(フロートしたボックスとしないボックスの関係)

良くあるHTML構造でフロートしてみます。div#wrapperの中のp#content1だけをフロートさせます。content1とcontent2にmarginを設定し、paddingとborderは全てゼロです。

HTML

<div id="wrapper">
  <p id="content1">
     ・・・
  </p>
  <p id="content2">
     ・・・
  </p>
  <p id="content3">
     ・・・
  </p>
</div>

CSS

#wrapper {
   width: 450px;
   border: dotted 1px;
}
#content1 {
   float: left;
   width: 160px;
   margin: 20px;
}
#content2 {
   margin: 10px;
}
#content3 {
   margin: 0px;
}

CONTENT1
Morbi eu arcu id ipsum aliquet lobortis. Pellentesque suscipit, quam at condimentum pharetra, nunc eros rhoncus metus, id luctus enim arcu vel risus.In urna leo, porttitor eget, tempus ut, fermentum non, libero. Ut aliquet. Ut consequat. Proin varius, dui ac mollis pulvinar, elit nulla feugiat nisi, a vehicula nisl magna ut nulla. Mauris gravida nunc ut augue. Donec leo. Aenean lorem mi, gravida eget, adipiscing ut, aliquam nec, mauris.

CONTENT2
Suspendisse at neque sit amet ante hendrerit porta. Maecenas sit amet ante quis pede ultricies consectetuer. Curabitur pellentesque faucibus nisi. Maecenas a dolor at massa fringilla adipiscing. Donec blandit vehicula nisi. Aliquam sem neque, tincidunt eu, ornare nec, tristique vitae, felis.

CONTENT3
Sed vel orci nec dui ullamcorper porttitor. In dapibus, sapien vitae semper gravida, nisi sem cursus justo, vel luctus quam velit a metus. Pellentesque sed lorem. Sed fringilla accumsan lacus. Suspendisse feugiat ipsum ac odio.
Donec adipiscing. Fusce placerat vehicula nunc. Donec nibh. Duis purus. Quisque diam. In mattis erat quis ligula. Nulla cursus risus. Ut tempus tincidunt enim. Suspendisse mi tellus, consequat et, vehicula ac, facilisis sed, pede. Praesent odio. Nam lorem. Suspendisse feugiat. Morbi justo arcu, dapibus vitae, aliquam sit amet, pulvinar ac, mauris.

  • 要素のボックスをフロートするので、何らかの形で幅(通常width)が指定されていること。
  • フロートされたボックスは外側のボックスの上、端(左右)に、マージンを縁として配置される1
  • テキスト:先行するフロートされたボックスに続くテキストは隣接する。隣接しなければ回り込む。
  • ボックス:フロートされたボックスに続くフロートじゃないボックスは、フロートボックスは無かったかのように配置される。重なる場合はフロートされたボックスの背面にボックスの背景とボーダーが隠れる。

外側のボックスの高さについて

floated div with nocontentフロートボックスは、それを内包しているボックスの高さを広げてくれません。従って、上記の例で、#container2も(つまり内包ブロック全て)フロートさせると、以下のようにdiv#wrapperの高さはゼロになります。これを何とかするのがclearfixハックですが、他にも、ボックスの最後にカラの要素(フロートしてない)を入れてclear:bothすれば高さが出ます。

B.ボックスのフロート基本(フロートボックス同士の挙動)

  • 内側のフロートボックスのマージンが、外側のボックスの端につっかかるまで移動する。
    floatd explanation 2
  • 次のフロートボックスのマージン外縁は、最初のフロートボックスの端に突っかかるまで移動する。
  • カラム落ち:外側のボックスに入りきらないと、フロートボックスは下段におちて外側のボックス端まで移動する。
    floatd explanation 3
  • 上記の際に途中にフロートボックスの端があると、そこでつっかかって止まる。
    floatd explanation 4

C.ネガティブマージンによるフロート

通常HTMLの記述ではsidebarは以下のようにdiv#sidebarはdiv#maincontentの後にあります。
これをマイナスマージンでsidebarをmaincontentの左に持っていくやり方の考え方です。実際のレイアウト(fixed, liquid, elasticなど)については別途記事にする予定です。

HTML

<div id="wrapper">
  <p id="maincontent">
     ・・・
  </p>
  <p id="sidebar">
     ・・・
  </p>
</div>

float: left;の場合で説明します。

  • 基本:左にフロートされたボックスの後に、さらに左にフロートされたボックスがある場合、後のボックスのマージン左辺が、前のボックスのマージン右辺より左にあってはならない。同じ事が右にフロートされたボックスにも当てはまる。
    negative margin 1
  • 最初のボックスのマージン右辺を左側に大きく振ります(margin-right: -200pxとか)。
    negative margin 2
  • 次のフロートされたボックスの左辺が、前のボックスの右辺を探しながら、右からやってくる。2007/5/24追記:下の図では外側の縁(#wrapper)に、前のボックスの右辺がつっかかって止まっているようになっていますが、実際には引っ掛かるのは左辺なので、最初のボックスのmargin-left:100pxとかがないとこのようになりません。すみませんでした
    negative margin 3
  • 最初のボックスは、次のフロートボックスを左へ受け流し、左に振ったマージン右辺のところまで、次のボックスがフロートして配置される。
    negative margin 4
  • 別のケースで、最初のボックスの左マージンを大きくとって、次のボックスの左辺を大きく右に振ります(margin-left: -200pxとか)。
    negative margin 5
  • 後にフロートされたボックスの左辺が、前のボックスの右辺にぶつかるまで左へ流れて止まる。
    negative margin 6

D.IE6様対策

ここではフロートレイアウトに影響するバグと対策だけ記述します。

1.widthの解釈

IE6 quirks mode
有名なwidthの解釈の違いです。レイアウト上は致命的です。「widthのある属性にpaddingやborderを使わない」ということにつきます。
「floatにはwidthを指定する」「widthとpadding, borderを使わない」を合わせると、

floatした要素にはpadding, borderを使わない。

になります。paddingしたい場合はHTML構造で中にもう一つコンテナを作ってそこでpaddingやborderを指定するようにします。そうすればレイアウト上の苦労は少なくなります。

2.”have layout”問題

“have layout”プロパティを持つ要素はサイズや位置がコントロールされます。持ってない要素では親要素に従ってレイアウトされます。
“have layout”になるのは以下のような場合です。

  1. body, table, tr, td, img, hr, input, select, textarea, button, iframe, embed, object, applet, marqueeの各要素
  2. position: absolute; が指定された要素
  3. float: が指定された要
  4. display: inline-block; が指定された要素
  5. width, height が指定された要素

“have layout”にはいろんな問題があります。以下は一部です。

テキストが回り込まずにボックスになる。
本来(フロートしてない)テキストに関しては、フロートしたボックスの周りに回り込むべきですが、haslayoutの場合、ボックス型になってしまいます。これを避けるには、haslayoutにならないようにするしかないようです。
IE haslayout bug
widthを指定していても、幅が勝手に広がる。
widthを指定しているボックスは大きくしないであふれたテキストは次行に送って欲しいところですが、haslayoutの場合、はみ出したテキスト分だけwidthを無視して幅を広げてしまいます。これも、has layoutにならないようにするか、widthのあるボックスの内側にボックスを作ってそこにテキストを流すことで回避できます。
IE haslayout bug 2

3. margin double 問題

私はこのマージンが二倍になってしまう問題に良く出くわします。ただ、見てすぐわかるのと、解決方法が簡単なので、覚えるだけです。フロートしている要素にdisplay:inline;を足すだけです。他のブラウザには影響しません。
doublemargin.png

4. その他のバグ

duplicate character 問題
ボックスの最後の数文字が、ボックスの下に重複して出現するバグです。連続する2つ以上のコメントが、フロートした要素のあいだに入っていることが2回以上あると発生します。
このような現象が出たら、連続するHTMLコメントを疑ってください。
peek-a-boo バグ
フロートした要素の後の、フロートしていない要素が、消えてしまう現象で、なぜかページをリロードすると出現します。この現象の発生条件は、①フロート要素の後にフロートしていない要素があり、②その後にclearした要素があり、それがフロートした要素に接触していて、③これらを内包する親ボックス要素にwidthやheightが設定されいない、かつ背景の色かイメージが設定されている。です。
解決するにはフロートした要素にposition: relative;を付け加えるだけです。

結局FirefoxかOperaでレイアウトを確認して、正しくレイアウトされてから、IE6で確認し、おかしかったら同じ現象のバグを検索するしかないでしょう。

  1. 「垂直マージンの相殺」については別途記事にする予定ですが、フロートとは関係ありません。

Related Posts

Trackback URL

6 Trackbacks/Pingbacks

  1. [...] フロートとネガティブマージンまとめ:CSS | Tech de Go (tags: css layout float) [...]

  2. [...] フロートとネガティブマージンまとめ:CSS | Tech de Go (tags: css webdesign) [...]

  3. フロートとネガティブマージンまとめ:CSS…

    フロートとネガティブマージンまとめ:CSS…

  4. [...] フロートとネガティブマージンまとめ:CSS | Tech de Go [...]

  5. CSSを使ってHPを作った仕事のまとめ備忘録…

    複数のCSSを外部ファイルにする場合、import.cssを作ろう
    import.css内には読み込む外部cssファイルをまとめておくべし。新規でCSSファイルを作った場合はimport.cssと新規のCSSファイルをアッ…

  6. フロートを組むと、IEで文字の一部が下に複製される…

    去年からずーっと後輩のNちゃんと悩んでいた事。それはフロートを組んだときに、右側のボックスエリアにある文字の一部が下に複製されてしま……

Post a Comment

Your email is never published nor shared.