CSSのfloatを入門者みんなに理解してほしい

CSSでflexboxやgridが使えるようになってからfloatを利用してページを作成している例を見ることも少なくなりました。floatを学ぶ前にflexboxを学ぶことをお勧めします。この記事を書いてからfloatを設定した記憶がありません。しかし古いサイトを管理している人であればfloatを見かける人もいるかもしれません。floatが出てきても困らないようにfloatの理解をしておきましょう。
float(フロート)の話を始める前に、まずdiv, h1, p等のブロック要素の特徴を理解しておく必要があります。ブロック要素には下記の特徴があります。
親要素の幅一杯に領域が広がり、ブロック毎に自動で改行が行われる
そのブロック要素の特徴により通常は下の図の左側のレイアウトしかとることはできません。その問題を解決するために利用するのが、CSSのfloatプロパティです。floatプロパティを利用すれば、ブロック要素を使って右側のレイアウトに変更することができます。しかし、変更するためにはいくつかルールがあり正しくレイアウトを制御するためにはそのルールを理解しておく必要があります。本文書では、floatを利用する上で必要となるルールについて説明を行っていきます。

目次
事前準備
floatを理解していくための事前準備として、シンプルなレイアウトのページを作成します。containerクラスで、header, main, sidebar, footerの4つのクラスを囲みます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>CSSのfloatをみんなに理解してほしい</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="header"></div>
<div class="main"></div>
<div class="sidebar"></div>
<div class="footer"></div>
</div>
</body>
</html>
各要素を簡単に識別できるようにすべての要素に背景色をつけています。
.container{
width:1000px;
background-color: #cbc9ff;
}
.header{
background-color: #a8d7c5;
height: 100px;
}
.main{
background-color: #f4f3ac;
height:250px;
}
.sidebar{
background-color: #fad0b4;
height:250px;
}
.footer{
background-color: #f3a5a1;
height:100px;
}
上記のHTMLとCSSを使うとdiv要素はブロック要素であるため、下記のようなレイアウトのページになります。

mainとsidebarのブロックを使って2コラムレイアウトとするため、mainとsidebarのみ幅の変更を行います。
.main{
background-color: #f4f3ac;
height:250px;
width:600px
}
.sidebar{
background-color: #fad0b4;
height:250px;
width:400px;
}
幅を変えるとmainの右側には、領域が生まれますが、その空いた領域に自動で、sidebarの領域が入ることはありません。また、幅を変えたことで今まで見えていなかった親要素のcontainer領域が見えるようになります。ここまででfloat設定前の準備は完了です。
親要素のcontaninerは、header, main, sidebar, footerの下にも隠れて見えないだけで存在はしています。

floatとは
floatは、floatプロパティを設定した要素を横並びにする機能です。通常では、ブロック要素は縦にしか並ぶことができませんが、CSSのfloatプロパティの設定をleftにすることで、上の要素から順番に左から並び、rightに設定することで、上の要素から順番に右から並びます。それぞれのブロック要素に個別にfloatを設定する必要があります。

floatの設定で領域が消える
実際にmainのみfloatのleftを設定します。
.main{
background-color: #f4f3ac;
height:250px;
width:600px;
float:left;
}
float設定をmainのみ行った結果、sidebarが画面から消えてしまいます。実際には、sidebarの領域は消えたわけではなく、mainの下に移動して、見えなくなっているだけです。mainのopacityプロパティを0にするとsidebarの存在がわかります。

mainのみfloat left
実際は下記のようにmainの下にsidebarが隠れている状態です。

sidebarがmainの下に隠れる
floatという単語は、英語で浮く、浮かぶという意味を持ち、floatのleftを設定したmainの領域が浮いた状態になり、浮いた結果、その下にsidebarが入りこんでいる状態になっています。これでなぜfloatと呼ばれるのか意味が少しわかってもらえたかと思います。
よりfloatを理解してもらうため、sidebarにもfloatを設定します。mainのfloat設定はleftのままです。
.sidebar{
background-color: #fad0b4;
height:250px;
width:400px;
float:left;
}
今度は、mainとsidebarにfloatを設定した結果、画面からfooterの領域が消えてしまいました。先ほどのsidebarと同様にfooterは消えたのではなく、mainとsidebarがfloatで浮いた結果、その浮いた領域の下にfooterが入りこんでいるため、見えなくなっている状態です。

main,sidebar float left
footerの領域は下記のようにmainとsidebarの下に隠れています。

隠れているfooter
floatをclearする(解除する)
floatを設定した結果、mainとsidebarの領域は横並びになりましたが、footerの領域が下に隠れてしまいました。この問題は、floatを解除することで解決します。floatの設定を行った場合は、必ず他の要素を使用して、floatの解除を行わなければなりません。floatの解除を行うプロパティがclearプロパティです。clearプロパティの設定値には、左のfloatを解除するleft、右のfloatを解除するright、左右両方のfloatを同時に解除するbothがあります。ここではbothを使用していますがfloatのleftのみ設定しているので、leftでも解除可能です。
下記のようにfooterクラスにclearプロパティを設定します。
.footer{
background-color: #f3a5a1;
height:100px;
clear:both;
}
floatを解除した結果、mainとsidebarが横並びになった2コラムレイアウトを実現することができました。

2コラムレイアウト
ここまでのレイアウトはシンプルだったため、footer要素でfloat解除を行えば目的のレイアウトを作成することができました。しかし、実際の場合、途中でレイアウトを変更したため、floatの制御がうまくいかずレイアウト崩れが起こることが多々あります。よく陥りそうな例を使って別のfloatの解除方法を説明していきます。
div要素の高さが0になる場合の対応
下記のようにmainとsidebarのみ中央寄せへの変更があった場合を考えます。中央揃えを行うためにmainとsidebarに新規の親要素のdivを追加して幅とmarginの設定を行います。

mainとsidebarを中央表示
新規でmainとsidebarを囲むwrapperクラスを追加しています。
<div class="container">
<div class="header"></div>
<div class="wrapper">
<div class="main"></div>
<div class="sidebar"></div>
</div>
<div class="footer"></div>
</div>
wrapperの幅を1000pxとして、marginで中央揃えにしています。
.container{
background-color: #cbc9ff;
}
.wrapper{
width:1000px;
margin:0 auto;
background-color: red;
}
ブラウザで見るとmainとsidebarが中央揃えになっているため、問題ないようには見えるのですが、実は、親要素の設定したwrapperの高さが0になっています。強調するため、wrapperの領域を赤線にしていますが、実際に赤線の高さはなく、wrapper領域の高さは0になっています。(ChromeのDeveloperツールを見ると確認できます)

wrapper要素の高さが0
wrapper領域の高さが0になった理由は、下記の左側の図のようにfloatを設定しているmainとsidebarを含むwrapper要素の外側にfloatの解除を行うclearプロパティを持つfooter要素があるためです。下記の右側の図のようにwrapper要素の中にclearプロパティを持つ要素を追加すれば、この問題は解消します。
高さ0の問題を解決するためには、右図のようにwapper要素の中にfloatの解除を行う別の要素を追加しなければいけません。

wrapperに新規のブロック追加
追加のブロック要素otherを追加します。
<div class="container">
<div class="header"></div>
<div class="wrapper">
<div class="main"></div>
<div class="sidebar"></div>
<div class="other"></div>
</div>
<div class="footer"></div>
</div>
これまでfooterでfloatの解除を行っていましたが、otherでfloatの解除を行っています。
.other{
height:100px;
clear:both;
}
.footer{
background-color: #f3a5a1;
height:100px;
}
ブラウザで確認すると新たに追加されたother領域が表示され、wrapper領域の高さは0から350px(main+otherの高さ)になります。otherクラスの背景は設定していないため、親要素であるwrapperの背景色の赤を確認できることでwrapper領域に高さがあることが確認できます。

divのブロック要素 otherを追加
clearfixを使用してfloatを解除する
floatの解除を行う場合、追加領域を加えることが可能な場合やすでに存在している場合はその要素でfloatの解除を行えば問題はありません。しかし、floatの解除を行う領域がない場合は別の方法で、floatを解除し、wrapperの高さを保持させなければなりません。そのために利用するのがclearfixです。floatを設定している要素(ここではmain, sidebarの親要素であるwrapper)にclearfixクラスの追加を行い、floatの解除を行います。
<div class="container">
<div class="header"></div>
<div class="wrapper clearfix">
<div class="main"></div>
<div class="sidebar"></div>
</div>
<div class="footer"></div>
</div>
clearfixは、クラスを追加した要素の後に疑似的に中身のないブロック要素を作成し、そこでfloatの解除を行っています。
.clearfix:after{
content : '';
display: block;
clear:both;
}
clearfixを設定を行うと先ほどのようにother領域を追加することなくwrapper要素の疑似要素であるafterによって、floatの解除を行います。

clearfixでfloatを解除
overflowを使用してfloatを解除する
別要素へのclearプロパティの設定、親要素へのclearfixの追加以外にもfloatの解除を行う方法があります。CSSのoverflowプロパティを利用すれば、clearfixと同じようにfloatを解除し、親要素の高さを保持することが可能です。
floatを設定しているmain, sidebarの親要素であるwrapperにoverflowプロパティを下記のように設定します。値は、hiddenを使用します。
.wrapper{
width:1000px;
margin:0 auto;
overflow:hidden;
}
overflowを設定することで、clearfixと同様にfloatの解除を行い、親要素に高さを持たせることができます。