CSSのbox-sizingでwidthとpaddingの計算方法を変える(content-box vs border-box)

CSS で width を指定したのに、padding や border を足すと想定より大きくなってしまう。この問題を解決するのが box-sizing プロパティだ。ボックスの「幅」が何を含むかを切り替えることで、レイアウト計算がシンプルになる。

content-box(初期値)

初期値の content-box では、width はコンテンツ領域の幅だけを指す。padding と border は width の外側に追加されるため、実際の描画サイズは width + padding + border になる。

HTML
CSS
JavaScript
<div class="content-box-demo">
  <div class="info">width: 200px</div>
  <div class="info">padding: 20px</div>
  <div class="info">border: 2px</div>
  <div class="info">実際の幅: 244px</div>
</div>
.content-box-demo {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 2px solid #ef4444;
  background: #fef2f2;
  font-size: 13px;
}
.info {
  margin: 4px 0;
}

width: 200px に padding 左右 40px と border 左右 4px が加算され、合計 244px で描画される。レイアウトを組むたびにこの計算をするのは手間がかかる。

border-box

border-box を指定すると、width が padding と border を含んだ値になる。つまり width: 200px と書けば、padding や border がどれだけあっても要素の外形は 200px に収まる。

.box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 2px solid #3b82f6;
}
/* 実際の幅は 200px(コンテンツ領域が自動で縮む) */

コンテンツ領域は 200 - 40(padding)- 4(border)= 156px に自動調整される。width が最終的な描画幅と一致するため、レイアウトの見通しが格段によくなる。

2 つの違いを視覚的に比較する

content-box

width = コンテンツ領域のみ。padding と border は外側に加算される。幅の計算が複雑になりやすく、レイアウト崩れの原因になることが多い。

border-box

width = コンテンツ + padding + border の合計。指定した幅がそのまま要素の外形になる。直感的で計算が簡単。

全称セレクタでリセットする

実務では、すべての要素に border-box を適用するのが標準的なやり方だ。CSS リセットや Normalize.css にもこの指定が含まれていることが多い。

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

疑似要素(::before, ::after)にも適用するのがポイントだ。これを忘れると、疑似要素だけ content-box のままになり、微妙なレイアウトのずれが発生する。

CSS のリセットファイルの冒頭にこの 4 行を書いておけば、以降のスタイリングで width の計算に悩むことはほぼなくなる。

width: 100% との関係

border-box が特に効果を発揮するのが width: 100% と padding を同時に使う場面だ。

content-box + width: 100% + padding

親の幅いっぱい(100%)にさらに padding が加算されるため、親要素からはみ出してしまう。横スクロールが発生する典型的なパターンになる。

border-box + width: 100% + padding

padding を含めて親の幅に収まるため、はみ出しが起きない。フォーム入力欄やカードコンポーネントで安心して使える。

/* content-box だとはみ出す */
input {
  box-sizing: content-box;
  width: 100%;
  padding: 12px;
  /* 実際の幅 = 親の100% + 24px → はみ出す */
}

/* border-box なら収まる */
input {
  box-sizing: border-box;
  width: 100%;
  padding: 12px;
  /* 実際の幅 = 親の100%(padding込み) */
}

フォームの input や textarea は初期状態で content-box のブラウザもあるため、全称セレクタでのリセットが特に重要になる。border-box を前提にしたコーディングは、現代の CSS 開発における基本中の基本と言ってよい。