Last updated on

box-sizing とインナー幅——原則 border-box、インナーコンテナだけ content-box にする理由

  • CSS
  • レイアウト
  • box-sizing
  • レスポンシブ

box-sizing は「width / height に padding と border を含めるか」を決めるプロパティです。実装では 原則 border-box にしつつ、コンテンツ最大幅を持つインナーコンテナだけ content-box に寄せる、という分け方には明確なメリットがあります。


content-boxborder-box の違い(おさらい)

  • content-box(初期値)
    width / heightコンテンツ領域のみpaddingborderその外側に加算される。
  • border-box
    width / heightpadding と border を含んだ枠までを指す(中身のコンテンツ領域は、指定幅から padding を引いた分になる)。

原則 border-box、例外は「インナーコンテナ」

案件では 全体を border-box にそろえることが多いです。リセット CSS で次のように * と疑似要素へ直接 border-box を指定している例もあります(コメントは意味の要約です)。

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

ここまでが前提のとき、.l-inner のように「インナー幅+左右ガター」を一つのクラスで表現するインナーコンテナだけ、content-box に切り替える判断がしばしば有効です。


なぜ max-width だけで済ませたいのか

border-box のまま 同一要素max-widthpadding-inline を両方載せると、max-widthborder box の上限になります。つまり、見かけの コンテンツ幅は max-width から左右の padding を引いた値になります。

そのため、デザイン(Figma など)で与えられた 「インナー=コンテンツ幅」 をそのまま max-width に載せたい場合、次のどれかが必要になります。

  • max-width: calc(var(--inner) + var(--inner-padding) * 2); のように 数値を足す
  • インナーコンテナを二段に分け、内側だけに max-width、外側だけに横 padding を載せる
  • その要素だけ content-box にし、max-width: var(--inner); のように インナー幅をそのまま書く

3 番目を選ぶと、デザイントークンと max-width を 1 対 1で結べるので、トークン運用やレビュー時の読み取りが楽になります。


width: 100% は付けない方がよいことが多い

.l-inner を次のように書く案があります。

.l-inner {
  margin-inline: auto;
  box-sizing: content-box;
  max-width: var(--inner);
  width: 100%;
  padding-inline: var(--inner-padding);
}

box-sizing: content-box のとき、width: 100%コンテンツ幅を親の幅いっぱいにします。padding-inlineその外側に加算されるため、親幅ぴったりに収めたい意図でも 100% + padding で横にはみ出しやすいです。

通常フローの ブロック要素であれば、**width を省略(既定の width: auto)**したままでも、多くの場合 親の利用可能幅に収まる振る舞いになり、margin-inline: automax-width とも相性が良いです。そのため .l-inner から width: 100% を外すのが無難です。

例外として、flex アイテムや grid アイテムとして min-width: auto 由来の縮み・はみ出しを抑える目的で width: 100% が入っていることはあり得ます。その場合は min-width: 0 など別解がないかもあわせて検討するとよいです。


リセット方式との注意(補足)

* { box-sizing: inherit; } のように inherit で揃える方式だと、親を content-box にしたとき 子孫へ伝播してしまうことがあります。一方、本稿冒頭のように 各要素へ border-box を直接指定するリセットであれば、子は引き続き border-box のままになりやすく、親のインナーコンテナだけ content-box にする運用と相性がよいです。


まとめ

  • 全体は border-box でよい。width: 100% と padding の同居も扱いやすい。
  • インナー幅+ガターを一要素で持つなら、そのインナーコンテナだけ content-box にして max-width にインナー値を直書きできるようにする、は合理的な分割です。
  • そのインナーコンテナがブロックなら、width: 100% は外して 100% + padding の横溢出を避けるのが安全です。
  • border-box のまま二層に分ける方法もあり、チームの好みと HTML の厚みで選べます。