floatの基礎

フロートについて

フロート … CSSでレイアウトを組んでいくときに、誰もが使っていると思います。フロートは要素を左、または右に寄せてくれる便利なプロパティ。でもフロートは、それ自身だけでなく他の要素へも影響してしまいます。正しく使わないと、カラム落ちやレイアウト崩れを起こしてしまいますよね。

ここではフロート自体の性質と、他の要素に与える影響などを見てみましょう。そうする事によって、なぜレイアウトが思うように組めないのか … などが見えてくると思います。基本がわかれば、解決策を見つけるのも早くなるかもしれませんね!

①フロートとは?

フロートとは、要素のボックスを通常フローから取り外し、左、または右に移動させること。浮動化ともいいます。そしてフロートさせたボックスには、 width を指定しなくてはいけません。

でも、width 属性を指定してある img 要素や、size 属性を指定してある select 要素など、大きさがはっきり分かるものは、width プロパティーを指定しなくても OK です。

また、通常フローの中のインラインボックスには、width を指定しても有効になりませんでしたが、インラインボックスはフロートさせるとブロックボックスになるため、width を指定できるようになります!

実際には width を指定しなくても、内包する要素の幅にフィットします … でも決まりなのでしっかり width を指定するようにしましょう!

さて、それでは実際に要素をフロートさせてみます。float プロパティーで指定できるのは、以下の3つですね!

float: left;
float: right;
float: none;
none はフロートさせないという事なので、ここでは float: left を例に見てみましょう。float: right は左右が入れ替わるだけなので、左を右と読み変えてください。

float: left

左に寄せられたブロックボックスを生成します。後に続く要素は、そのブロックボックスの上辺から右側に回り込みます。

ちょっと難しい言い回しですねー。とにかく float: left を指定すると、インライン要素もブロックボックスを生成して、左側によせられます。そして後に続く要素にも影響を与えます。フロートの後に続く要素は、右側に回り込むんですね。

フロート例①

●html
[p]
[img src=”image.jpg” alt=”” /]
フロートとは …
[/p]

●css
img{
width: 200px;
float: left;
}

フロート例②

2カラムレイアウトや、3カラムレイアウト、横並びのナビゲーションなど、とにかくフロートは頻繁に使いますよね。フロートした後は解除しないと、後続の要素も同じようにフロートされちゃって、レイアウトがぐちゃぐちゃになっちゃいます。下の例は一番簡単な方法 … 後続の要素に clear プロパティを使う方法です。

#main は左フロート、#sidebar は右フロート(左でもOKです。)で左右に振り分けます。そのままだとフッターがサイドバーの方に回り込んでしまうので、clear:both でフロートを解除します。 それから clear した要素では、margin-top が反映されない場合があるのも要チェックです!ちょっと下の画像を見てください。

②フロートの厳格な配置ルール

1、左にフロートされたボックスの左外辺(マージンがある場合はマージンの左辺)が、包含ブロックの左辺より左側にあってはならない。同じ事が右にフロートされたボックスにも当てはまる。
つまり包含ブロックからははみ出ないということですねー。

2、左にフロートされたボックスの後ろに、別の左にフロートさせたボックスがある場合、後ろのボックスは前のボックスの右側に配置されるか、下に配置されなければならない。同じ事が右にフロートされたボックスにも当てはまる。
(これは右に空いてるスペースによりますね!収まりきれれば右側に、収まりきれなければカラム落ちのような状態になりますよ!ということですねー。)

3、左にフロートされたボックスの右外辺(マージンがある場合はマージンの右辺)が、右側にフロートされたボックスの左外辺より右にあってはならない。同じ事が右にフロートされたボックスにも当てはまる。
(言い回しが難しいですけど、フロートしたボックス同士は重ならないって事ですね!)

4、フロートされたボックスの上外辺は、包含ブロックの上辺より上にあってはならない。
(これは簡単ですねー!包含ブロックからははみ出ません。)

5、フロートされたボックスの上外辺(マージンがある場合はマージンの上辺)は、それ以前の要素が生成したブロックボックス、またはフロートボックスの上外辺より上にあってはならない。 (2カラムレイアウトを例に考えると分かりやすいですねー!2番目にフロートしたボックスが、先にフロートしたボックスの上辺より上にくることはありません。)

6、フロートされたボックスの上外辺(マージンがある場合はマージンの上辺)は、それ以前の要素が生成したボックス内の行ボックスの上辺より上にあってはならない。
(これもさっきと同じように2カラムレイアウトで考えれば納得ですね!)

7、左にフロートされたボックスの後に、別に左にフロートされたボックスがある場合、後ろのボックスの右外辺が包含ブロックの右辺より右にあってはならない。同じ事が右にフロートされたボックスにも当てはまる。
(これも簡単、包含ブロックからははみ出ません。その結果、幅が入りきらなければ下にレイアウトされますよね!)

8、フロートされたボックスは出来る限り上に配置されなければならない。
(余分な空白はできずに、可能な限り上に配置されますよね!)

9、左にフロートされたボックスは、出来る限り左側に。右にフロートされたボックスは、出来る限り右側に配置されなければならない。また、後に続くフロートされたボックスよりも、優先的に上方に配置されます。
(優先的に上方に … という部分は、もしカラム落ちするのであれば、後から配置された方が下に配置されて、先に配置された方が上に配置される … ということですね!)

10、フロートされたボックスに clear プロパティーが適用される場合、そのボックスの上辺は、「clear:left」の場合はそれ以前の全ての左にフロートされたボックスの、「clear:right」の場合はそれ以前の全ての右にフロートされたボックスの、「clear:both」の場合は左右両方にフロートされたボックスの下外辺よりも下に配置されなければならない。
(ちょっと長いですけど … clear したボックスは、フロートしたボックスよりも下に配置されるってことですね!)

「CHECK POINT」
フロートさせたら、width も一緒に指定する。
インラインボックスはフロートさせるとブロックボックスになる。
フロートは、通常フローから外れます。

clear プロパティーとは

フロートを解除するときは、clear プロパティーを使いますよね!clear プロパティーは、横に配置するという流れを止めて、フロートの下に配置させる為のプロパティーです。ご存知の通り、以下の三種類の値がありますよね!

clear: both;
clear: left;
clear: right;
さて、それでは実際によく使われているレイアウト、2カラムレイアウトを作って、clear プロパティーを試してみましょう。

[div id=”container”]
[div id=”header”] … [/div]
[div id=”main”] … [/div]
[div id=”sidebar”[ … [/div]
[div id=”footer”] … [/div]
[/div]

ブラウザでの表示

いろいろ余計なプロパティーも書かれていますが … まずは左カラム 2、右カラム 3を見てみましょう。両方 float: left が指定してあります。右カラムは float: right じゃないの?って声も聞こえてきますが、今回は float: left を指定してみました。

float: left

左に寄せられたブロックボックスを生成します。そして後に続く要素は、そのブロックボックスの上辺から右側に回り込みます。

という訳なので、別に float: right じゃなくても OK なんですねー。後に続く要素(右カラム)が、ちゃんと右側に回り込んでいますね!

フロートさせるとマージンの相殺は起こりません

さて、マージンの相殺を見てきましたが、これはあくまで通常フロー内でのお話です。例えば下側の div要素2 2をフロートさせると、マージンは相殺されなくなります。 div をフロートさせた場合

フロートさせた要素は、通常フロー(流れ)から外されて、新たなフローを作る …つまり同一上の流れの中に入ってないんですねー。なので相殺されないで、ちゃんとマージンが足し算されています。
さて、通常のフロー(position: static)での配置を見てきました。改めておさらいしても、特に難しい事は無かったと思います …。でもここで登場した、通常フローや行ボックスという言葉は、フロートや相対配置、絶対配置などのところでも登場します。またマージンの相殺についてもキチンと押さえておきたいですね!
それではいよいよ通常の通常フロー以外の配置、まずはフロートについて見ていきましょう。

「CHECK POINT」
・上下に隣り合ってる要素通しには、マージンの相殺が起こります。
・入れ子関係にある場合も、マージンの相殺が起こる場合があります。
・フロートした要素のマージンは相殺されません。

①clear を指定した要素の margin-top が効かない?

上の図を見てみると、clear を指定した footer に margin-top: 20px を指定してあります。でも実際には余白が無くて、マージンが効いていないように見えます …。ここでもう一度、フロートの厳格な配置ルールの 10番を見てみましょう。

フロートされたボックスの下外辺よりも下に配置されなければならない。

このルールによって、clear した footer には自動的に余白が追加されています。ん?余白が追加されるっていっても、余白が無いから困ってるんじゃない … これは一体どういうことでしょう? ちょっと整理してみましょう

追加された余白(クリアランス)

まず、フロートされたボックスは、通常フローから外されます。なので本来なら、footer は header のすぐ下に配置されるはずです(通常フローで考えてくださいね!)。でもフロートの厳格ルールの 10番によって、フロートの下に配置されなければなりませんよね。そのために、クリアランスという余白が自動的に追加されているんです。

ですから、margin-top はフロートボックスとの余白に対してのものではなく、通常フロー同士のヘッダーとフッターの間の余白に対してのものなんです。なので … たとえばフロートボックスよりも高いマージンを指定すれば、キチンとマージンが効く事を確認できます。

マージントップを大きくしてみると …(フッターのマージンを 300pxに指定しました)

でも、実際にはこんな風に指定することはありませんよね!フッターとフロートボックスの間に余白を作りたい場合は、フロートしたボックス(#main、#sidebar)に margin-bottom を指定すれば OK です。フロートしたボックスのマージンは相殺されませんから、margin-bottom: 20 px とすれば、20px 分の余白ができます

そう … フロートした要素のマージンは相殺されません。なので上記の図の中、ヘッダー(margin-bottom: 20px) と フロートボックス(margin-top: 20px)の間の余白は、相殺されずに 40pxの余白ができているんですね!実際にはこんな風に指定する事は無いかもしれませんが、覚えておくといいかもです!

「CHECK POINT」
clear プロパティーはブロックレベル要素に指定しよう!
clear した要素には、クリアランスが自動的に追加されることがあります。

参考図

①フロートをもっと理解しよう

すこし大雑把にフロートを見てきましたが、ここからは少し整理しながら詳しく見ていきましょう。まず、絶対に覚えておきたい事。
何度か出てきましたが、フロートを指定した要素は通常フロー(通常の流れ)から外れます。ということは … 一体どうなるのでしょう?ちょっと例をみてみましょう。

●html
[p class=”c01″]
[img src=”image.jpg” alt=”” /]
フロートとは …
[/p]
[p]
フロートさせた要素には …
[/p]

●css
img{
width : 200px;
float : left;
}
p{
padding: 10px;
border: 1px dashed #d64e80;
background: rgba(255,255,255,.5);
}

 

まず、フロートは通常フローから外されてしまいます。このサンプルでの通常フローに属している要素は、ふたつの p 要素ですね!その通常フローから、フロート(浮動化)した画像は外されている … ということです。通常フローから外されているので、きちんと上の p 要素内に収まってないのも当然なんですねー。p 要素から画像がはみ出してるのはそういう訳なんです

逆を言えば、親要素の高さはフロートされた子要素の高さを含めない … という事が言えそうです!同じフローの中にないので、当然と言えば当然ですねー。

そして 2番目の p 要素 … これは通常フローなので、普通に 1番目の p 要素の次にブロックボックスとして配置されているんです。もし写真がなければ、以下のように表示されますよね!その状態と何も変わらないんです。

フロートした画像が無かった場合

フロートは浮動化。浮かせて動かして配置しているだけなんです。なので立体的に考えると、フロート性質が分かりやすいかもしれませんね!あれ?浮かせてるんだったら、どうして以下のように表示されないの?って思うかもしれませんね …。

こんな風に表示されないのは何で?

浮いてるのなら、上記のように重なって表示されないのはなぜなんでしょうか?ここでインラインボックスの所で学んだ、行ボックスを思い出してみてください。

行ボックスは、基本的に包含ボックスの幅いっぱいに広がります。でも間にフロートした要素がある場合に、幅が狭くなる場合があります。

とありました。思い出しましたか?今回のサンプルでは、間にフロートした画像が入っていますよね!なのでその分行ボックスが縮んで、以下のように表示される … という訳なんですね!

縮んだ行ボックス

②フロートでレイアウトを作ってみよう!

目標のレイアウト

●html
[div class=”post”]
[h4][a href=”#”]フロートでレイアウトしよう![/a][/h4]
[img src=”image1.jpg” alt=”” /]
[p]
今回はフロートを使って …[/p]
[p]
[a class=”more” href=”#”]続きを読む »[/a][/p]
[/div]

それでは CSS でレイアウトしていきましょう。

1、まず一番外側のボックスの幅は 480px とします。
2、見出しである h4 要素の幅を指定して float: right で右に寄せます。幅は包含ボックスから、画像が入る分を引いて短くしておきます。
3、次に img 要素を float: left で 左に寄せます。見出しの width と画像の width の合計(margin や padding も含む)が、包含ボックスの幅と同じにするのがポイントです。
4、もし隙間があると、p 要素内のテキストが流れ込んできてしまうからです。
「もっと詳しく »」のリンクを float: right で右に寄せました
。 5、float を clear するために、div要素に clear: both を指定しました …

●css .post{
background:#fff;
padding:20px;
width:440px;
margin-bottom:40px;
clear:both;
/* 以下は丸角とシャドウは省略 */
}

h4{
width:290px;
float: right;
}

img {
width: 120px;
float: left;
padding :5px ;
background:#fff;
margin-right:20px; /* テキストとの距離 */
/* 以下、丸角とシャドウは省略 */
}

.more{
float: right;
}

ブラウザでの表示

惜しいです …。何度も言いますが、フロートは通常フローから外されてしまいます。その結果、通常フローである div 要素では、フロートした要素の高さを含みません …。
HTML のコードをいじらずにこの問題を解決する為には、ふたつ程方法があります。(他に方法があったら、教えていただけると嬉しいです!)

③overflow: hidden でフロート解除

ひとつ目は、div 要素に overflow: hidden を指定する方法です。先ほど「通常フローである div 要素では、フロートした要素の高さを含みません」と書きました。でもこれには続きがあります。

height の値が auto で overflow の値が visible 以外のブロックボックスが、そのマージン下辺よりも下にくるようなフロートを子に持つ場合、その高さはフロートを含むように広げられる。

そうらしいです。

という訳で、overflow の値を visible 以外 (scroll にするとスクロールバーが出てしまうので、hidden がいいかも)にしてしまえば、キチンとフロートした要素を包んでくれるようになります。この場合には、div に指定した clear: both は不要になります。

●css
.post{
background:#fff;
padding:15px;
width:600px;
margin-bottom:40px;
/* clear:both; これは不要 */
overflow : hidden;

でも本来 overflow: hidden は、切り抜く(はみ出す部分を隠す)プロパティーです。もし、ボックスの端ギリギリの要素に box-shadow でドロップシャドウをかけてあった場合、ドロップシャドウが隠されてしまい表示されない … ということもあるので、使用には注意も必要です。

clearfix でフロートを解除

●css
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: ” “;
clear: both;
height: 0;
}
/* clearfix for ie7 */
.clearfix{
display: inline-block;
}
.clearfix {
display: block;
}

clearfix には色々なコードがありますが、基本的には :after 疑似要素と content プロパティーを使ってブロックボックスを作り、そこに clear: both を指定するという手法です。Google で clearfix と検索すれば、たくさんコードが出てきますね!

この clearfix を親要素である div 要素にしていしてあげれば、キチンとフロートボックスを内包してくれるようにまります。この場合ももちろん、div 要素の clear: both は不要です。

●html
[h4]HTML[/h4]
[div class=”post clearfix”]
… 省略 …
[/div]

完成

今回書いた CSS のコードでは、一応 HTML に余分な装飾用のタグ(div タグ)を使わないでレイアウトすることができました。
とっても長くなってしまいましたけど、基本的なフロートの性質を見てきました。フロートを使いこなせば HTML に余計な装飾用の div 要素などを書かずに、
シンプルな HTML のままレイアウトできるようになります。その為にはフロートの決まりや性質をしっかりと覚えておきたいですね!

「CHACK POINT」
・clear プロパティーはブロックレベル要素に指定しましょう。
・行ボックスは、間にフロートした要素がある場合には幅が狭くなります。
・親要素の高さはフロートされた子要素の高さを含めません(overflow:hidden や clearfix を使う)。