今回は「要素からpaddingの部分がはみ出てしまう」「線がはみ出てしまう」というような問題をbox-sizingプロパティにより簡単に解決する方法を紹介します。CSS初心者の方でも分かるように box-sizingの意味から、使い方、各ブラウザの対応状況まで解説します。丁寧に解説していくので、中級者〜上級者の方は必要に応じて読み飛ばして頂ければと思います。

前提知識

あわせて読みたいCSSのwidth(幅)とheight(高さ)の指定方法をマスターしようあわせて読みたいCSSのmarginとは?paddingとは?余白の指定方法まとめ

1. box-sizingとは?

box-sizingは、CSSのボックスの寸法をどの範囲で計算するかを指定するプロパティです。このプロパティにより「要素の幅(width)と高さ(height)の中にpaddingとborderを含めるかどうか」という設定ができます(どういうことか後で図解します)。

1-1.box-sizingの基本値とinherit

固有の値はcontent-boxとborder-boxです。加えて、親から値を引き継ぐ共通値inheritも使えます。

  • box-sizing: content-box; ←初期値! paddingとborderを幅と高さに含めない
  • box-sizing: border-box; paddingとborderを幅と高さに含める
  • box-sizing: inherit; 親要素のbox-sizingの算出値を引き継ぐ

それぞれの値で具体的にどのような違いが出てくるのか見ていきましょう。


1-2. 値がcontent-boxの場合

paddingとborderを幅(width)と高さ(height)に含めない

box-sizing: content-boxは初期値です。ただし、buttonなどにはブラウザの既定スタイルでborder-boxが指定されることがあります。例として幅(width)で考えてみましょう。

box-sizing:content-boxの場合

値がcontent-boxの場合、widthで指定する幅の中にはpaddingとborderは含まれません。

通常フローでmarginも含めた横方向の占有幅を考えると、width + 左右のpadding + 左右のborder + 左右のmarginになります。pxでwidthやpaddingを指定する分にはこれでも別に良いのですが、問題はレスポンシブデザインのために%で指定するときです。

content-boxの欠点の話

親要素と子要素の幅の関係

図の「横の%合計は100%にしておくべき」は、親幅ちょうどに合わせる場合の一例です。常に100%にする必要はなく、余白を残す設計もできます。

なのでmarginを左右合計30%(各15%)に、paddingを左右合計30%(各15%)に、widthを40%に、などとして要素の作る幅を計100%にすれば、親要素にピッタリとはまっていい感じになるわけですね。%とpxを混ぜることもできます。たとえばcalc()で固定のpaddingやborderの分を引けば、content-boxでも親幅に合わせられます。

box-sizing: content-boxの状態で%指定したときに、あきらかに問題になるのはborderを含めるときです。borderの太さは%指定ができません。

border

たとえばwidthとmarginとpaddingで計100%であっても、borderの太さを5pxにするとその分だけ親要素からはみ出てしまうわけですね。

borderの幅には%を使えませんが、pxのほかemなどの長さも使えます。単純に幅を足すだけでは、親幅からはみ出す場合があります。また「widthとmarginを%で指定して、paddingだけをpx指定」ということが難しくなります。(計100%にならず、親要素からはみ出てしまったり、アンバランスなスペースができてしまったりします)。content-boxでは、これらを含めて寸法を計算する必要があります。


1-3. 値がborder-boxの場合

paddingとborderを幅(width)と高さ(height)に含める

border-box

box-sizing: border-boxとすると、paddingとborderがwidthとheightの中に含まれるようになります。

つまりwidth: 50pxと決まっているなら、paddingとborderもその50pxの中に含まれるようになるのです。

border-boxの幅とpadding・borderの関係を示す旧図(無制限という説明は直後で訂正)

図の「どれだけ大きくしても変わらない」は正確ではありません。内容の幅は0より小さくならないため、左右のpaddingとborderの合計が指定幅を超えると、実際の外幅は大きくなります。たとえばwidth:50px、左右padding:30px、border:0なら、内容幅は0px、外幅は60pxです。

線が太くなれば、その分だけ中身が小さくなる

padding:0でborderだけで画像を囲った場合、borderを太くしてもwidthの値は変わりません。代わりに要素の中身自体が自動で小さくなります。内容幅は「width − 左右のborder」で、最小は0pxです。これは画像自身の内容領域の話で、一般の子要素や長い文字列まで自動的に縮小する意味ではありません。

border-boxはレスポンシブデザインで便利

border-boxは幅や余白を%で指定したいときに便利です。%指定はレスポンシブデザインを作るうえでは欠かせません(ウェブページを見る端末の大きさに応じて、要素の大きさを調整できるからです)。ではなぜbox-sizingは%指定をするときに便利なのでしょうか。その理由は「親要素にピッタリはまりやすくなるから」です。言い換えると横の%合計を100%にしやすくなるのです。

Box sizingのmarginとpaddingの考え方 02

widthの中にpaddingとborderが含まれるので通常フローで、左右のpaddingとborderの合計が指定幅以内なら、「width」と「左右のmargin」の合計を親幅の100%にすることで、親幅ちょうどに合わせられます。ただし図は、左右のpaddingとborderの合計が指定幅に収まる場合です。たとえば親幅100px、width:80%、左右margin:10%、左右padding:50pxなら外幅は100pxとなり、左右marginも加えると120pxです。内容自体のはみ出しにも別途対応が必要です。


1-4. content-boxとborder-boxの違いの例

では実際にcontent-boxとborder-boxの違いをコードで書いて見てみましょう。分かりやすくするために要素はオレンジ色に、親要素はグレイにします。

HTMLコード
<div id="contentbox"><!--content-boxの親要素-->
  <p>content-box</p>
</div>

<div id="borderbox"><!--border-boxの親要素-->
  <p>border-box</p>
</div>
CSSコード
#contentbox, #borderbox {
	/*以下、親要素を見やすい設定に*/
	background: silver;
	padding: 10px 0;
}

#contentbox p {
	box-sizing: content-box;
	}

#borderbox p {
	box-sizing: border-box;
	}

#contentbox p, #borderbox p{
/*どちらも同じ幅・余白設定に*/	
	width: 90%;
	margin: 5%;
	padding: 10px;
	border: solid 5px black;
	background:orange;
}
ブラウザ表示ブラウザ表示例

↑補足情報を書き込んでいます。content-boxで親幅ちょうどに合わせたい場合は、通常フローでwidth + 左右border + 左右padding + 左右marginの合計が親幅になるよう計算します。合計が親幅より小さくても、余白を残して収まります。border-boxの場合、width + 左右margin = 100%になっていれば、左右のpaddingとborderが指定幅以内なら親幅に収まります。図はその条件での結果であり、内容のはみ出しまで防ぐものではありません

このようにborder-boxを使うことで、%での幅・余白指定がものすごく楽になるのですね。


1-5. 値がinheritの場合

親要素のbox-sizingの算出値を引き継ぐ

box-sizing: inheritと指定した場合には、親要素からbox-sizingの算出値を引き継ぐことになります。親がcontent-boxならcontent-box、border-boxならborder-boxになります。このプロパティは通常は継承されないため、明示的にinheritを指定します。ブラウザの既定スタイルも含め、親の算出値を確認してください。

2. box-sizingの対応ブラウザと書き方の注意点

現在の主要ブラウザは接頭辞なしのbox-sizingに対応しています。以下は接頭辞なしの対応開始バージョンです。古いブラウザを対象にする場合は、その環境で確認してください。

2-1. 対応ブラウザ

ブラウザ種類

対応バージョン

Google Chrome

バージョン10以降

IE

IE8以降

Firefox

バージョン29以降

Safari

バージョン5.1以降

Opera

バージョン7以降

IEの行は過去の対応情報です。歴史的な実装の参考として『IE7以下でbox-sizingを使いたい』という記事もあります。


2-2. box-sizingが効かない?

期待した幅にならないときは、開発者ツールでbox-sizingの算出値と、他のルールによる上書きを確認します。marginはborder-boxに含まれません。またwidthがautoの場合や、幅を指定できない通常のインライン要素、paddingとborderが指定幅を超える場合、内容自体のはみ出しも確認してください。接頭辞の追加だけで解決するとは限りません。


2-3. 現在は接頭辞なしで指定する

現在の主要ブラウザ向けには、box-sizing: border-boxだけで指定できます。

接頭辞なしの指定

次の.boxを、適用したい要素のクラスに置き換えて使います。

.box {
  box-sizing: border-box;
}

3. border-boxを全ての要素に適用する方法

レスポンシブデザインのウェブサイトを作るのであれば、全ての要素をあらかじめbox-sizing: border-boxにしておくと楽でしょう。その方が作業中に混乱しづらくなります。具体的にはCSSに以下のように書いておきます。セレクタに*(アスタリスク)を使うと「全ての要素に対して適用させる」という意味になります。合わせて疑似要素に対しても合わせて指定しておくのが良いでしょう。

*, *::before, *::after {
  box-sizing: border-box;
}

4. まとめ

ここまでの内容をまとめておきます。