4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Frontend CSS – パート4】なぜ width: 100% なのにはみ出るのか?Box Model と box-sizing を理解する

4
Posted at

ChatGPT Image Jun 3, 2026, 09_03_22 AM.png

注意
この記事はAIの補助を受けて編集しています。

目次


1. 問題: なぜ width:100% なのに要素がはみ出すのか?

次のコードを考えてみましょう。

<div class="parent">
  <div class="child">
    ここにコンテンツ
  </div>
</div>
.parent {
  width: 300px;
  background: #eee;
}

.child {
  width: 100%;
  padding: 20px;
  background: #3498db;
}

多くの人は .child.parent にぴったり収まる(300px)と考えるでしょう。しかし実際には、.child親からはみ出して しまいます。

なぜでしょうか? デフォルトでは、width: 100%「コンテンツ領域 (content area) の幅を親のコンテンツ領域の幅の100%にする」 という意味です。paddingborder を追加すると、それらは width外側 に追加されるため、実際の表示幅が親を超えてしまいます。

これはCSSで最もよくある落とし穴の一つです。


2. 本質: CSS Box Model の構造

すべてのHTML要素は ボックス (box) です。Box Model はそのボックスの構造を定義します。

  • Content area: 実際のテキストや画像などが入る領域。widthheight はこのサイズを指定する。
  • Padding area: コンテンツとボーダーの間の余白。背景色・背景画像はここまで広がる。
  • Border area: 枠線。
  • Margin area: ボーダーの外側の余白。他の要素との間隔を空ける。

単純に言うと、デフォルトでは width はコンテンツ領域の幅だけを意味し、paddingborder はその外側に追加される ということです。

2.1. content-box – デフォルトの動作

content-boxbox-sizing のデフォルト値です。この場合:

実際の幅 = width + padding-left + padding-right + border-left + border-right

例:

.box {
  width: 200px;
  padding: 20px;
  border: 5px solid black;
}

実際の幅 = 200 + 40 + 10 = 250px

2.2. border-box – 実用的な解決策

box-sizing: border-box を設定すると、計算方法が変わります。

width = コンテンツ + padding + border

ブラウザはコンテンツ領域を自動的に縮小し、合計が指定した width に収まるようにします。

同じ例で:

.box {
  width: 200px;
  padding: 20px;
  border: 5px solid black;
  box-sizing: border-box;
}

コンテンツ幅 = 200px - 40px(padding) - 10px(border) = 150px


3. ブラウザが実際の幅を計算する仕組み

重要なポイント: width: 100% は、親の コンテンツ領域 (content width) を基準に計算されます。親が box-sizing のどちらを使っていても同じです。

例:

.parent {
  width: 300px;
  padding: 20px;
  box-sizing: border-box; /* 親は border-box */
}

.child {
  width: 100%;
  padding: 10px;
  box-sizing: content-box; /* 子はデフォルト */
}

段階を追って計算:

  • .parentwidth: 300pxpadding: 20pxborder-box なので、親のコンテンツ幅 = 300 - 40 = 260px
  • .childwidth: 100% → 親のコンテンツ幅 260px の100% = 260px(子のコンテンツ幅)。
  • 子には padding: 10px ずつ → 子の実際の幅 = 260 + 20 = 280px

結論: 子の幅は 280px ですが、親のコンテンツ領域は 260px しかありません。その結果、子要素は親の content 領域に収まらず、padding 領域まで入り込みます。ただし、親の border-box 全体は 300px なので、親のパディングが十分に大きければ、外側から見てはみ出しているとは限りません。しかし、親のパディングが小さい場合や子にさらにボーダーがあると、完全にはみ出す可能性があります。

width: 100% + 子の border-box が必ずはみ出さないわけではありません。 子のパディングやボーダーは子の合計幅を増やしませんが、それでも子が親のコンテンツ領域からはみ出してパディング領域に入り込むことがあります。


4. box-sizing: 解決策の本質

意味 width: 100% への影響
content-box width はコンテンツ領域のみ。パディング・ボーダーは外側に追加される。 パディングやボーダーがあると簡単にはみ出す。手動計算が必要。
border-box width はコンテンツ+パディング+ボーダーを含む。パディング・ボーダーは内側。 安全: パディング/ボーダーが合計幅を増やさない。ただし margin や Flexbox/Grid には注意。

推奨される解決策:

/* 方法1: 全要素に直接設定 (一般的) */
*,
*::before,
*::after {
  box-sizing: border-box;
}

全体設定の注意点: 一部のサードパーティ製コンポーネントやライブラリは content-box を前提としている場合があります。ただし、主要なフレームワーク(Bootstrap, Tailwind, MUI)は border-box または互換性のあるリセットを提供しています。より安全にしたい場合は、inherit パターンを使うこともできます。

/* 方法2: 継承を使った制御可能な全体設定 */
html {
  box-sizing: border-box;
}
*,
*::before,
*::after {
  box-sizing: inherit;
}

この方法を使えば、特定のコンポーネントだけ content-box に戻すことが可能です。


5. React + TypeScript での実践例

5.1 NG例 – padding + width:100% ではみ出す

// BadCard.tsx
import React from 'react';
import './BadCard.css';

export const BadCard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  return <div className="bad-card">{children}</div>;
};
/* BadCard.css */
.bad-card {
  width: 100%;
  background: #f8f9fa;
  padding: 24px;
  /* box-sizing はデフォルトの content-box */
  border: 1px solid #dee2e6;
}

このカードを幅600pxのコンテナに入れると、width: 100% = 600px、パディング48pxとボーダーを加えると合計が600pxを超え、はみ出します。

5.2 改善例 – box-sizing: border-box で修正

// GoodCard.tsx
import React from 'react';
import './GoodCard.css';

export const GoodCard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  return <div className="good-card">{children}</div>;
};
/* GoodCard.css */
.good-card {
  box-sizing: border-box;
  width: 100%;
  background: #f8f9fa;
  padding: 24px;
  border: 1px solid #dee2e6;
}

これでパディングとボーダーが width: 100% の内側に収まり、カードは親にぴったり収まります。

5.3 box-sizing の全体設定

/* global.css */
*,
*::before,
*::after {
  box-sizing: border-box;
}

この全体設定を適用すれば、パディングやボーダーによる width: 100% のはみ出しはほぼ気にしなくてよくなります。ただし、marginoverflowwhite-space、そして Flexbox/Grid などの特別なレイアウトルールには依然として注意が必要です(セクション8参照)。


6. margin とブロックレベル要素の落とし穴

marginwidth に含まれませんが、横方向のはみ出しを引き起こす可能性があります。

例:

.parent {
  width: 300px;
  background: lightgray;
}

.child {
  width: 100%;
  margin-left: 50px;
}

この場合、要素が占有する横方向のスペースは 300px + 50px となり、結果として親要素からはみ出します。

対処法:

  • width: 100% を持つ要素に横方向の margin を使うのは避ける。
  • calc() を使う: width: calc(100% - 50px); margin-left: 50px;
  • あるいは width: 100% を使わない – ブロックレベルの要素はデフォルトで width: auto になっており、これで十分な場合が多い。

width: autowidth: 100% の違いを明確に:
CSS2.1 によれば、ブロックレベル要素の width: auto は次のように計算されます:
包含ブロックの幅 – margin-left – margin-right – padding-left – padding-right – border-left – border-right
つまり、要素は利用可能なスペースを自動的に埋めるように広がりますが、パディングやボーダーが追加で外側に付くことはありません。
例:

.child {
  display: block;
  margin: 0 20px;
  /* width: auto (デフォルト) => width = 包含ブロックの幅 - 40px */
}

このように、width: auto を使えば width: 100% は不要で、マージンによるはみ出しも起こりません。
結論: width: autowidth: 100% は計算方法が異なります。多くの場合、auto の方が安全です。


7. min-width / max-width と Box Model

min-widthmax-widthbox-sizing の影響を受けます。

  • content-box: min-width はコンテンツ領域に適用。
  • border-box: min-width はパディングとボーダーを含む。

パーセント値を使う場合、min-widthmax-width の基準は 包含ブロックの幅 です(親の box-sizing は関係ありません)。ただし、box-sizing はその要素自身のどの部分が min/max の制限を受けるかを決めます。

画像の安全な例:

img {
  max-width: 100%;
  height: auto;
  box-sizing: border-box;
}

border-box を忘れると、パディングやボーダーがある画像ではみ出す可能性があります。


8. Flexbox・Grid と min-width: auto の注意点

Box Model だけですべてのはみ出し問題が解決するわけではありません
Flexbox や Grid の中では、border-box を使っていても要素がはみ出すことがあります。

よくある原因の一つ は、Flexbox/Grid アイテムのデフォルト値 min-width: auto です。仕様では、min-width: auto「内容の内在サイズ (intrinsic size)」 を最小幅とします。つまり、要素は自分の内容より小さくならないということです。これを上書きしない限り、長いテキストなどがあると親からはみ出します。

例:

<div class="flex-parent">
  <div class="child">とても長い長い長い長いテキストで改行されない</div>
</div>
.flex-parent {
  display: flex;
  width: 200px;
  background: #eee;
}

.child {
  box-sizing: border-box;
  width: 100%;
  padding: 16px;
  background: #3498db;
  /* white-space: nowrap; があるともっと悪化 */
}

border-boxwidth: 100% があっても、内容が長くて改行されなければはみ出します。

対処法:

  • Flexbox では子要素に min-width: 0 を設定する(内容より小さくすることを許可)。
  • overflow: hiddenword-break: break-word / overflow-wrap: anywhere を使う。
.child {
  min-width: 0;          /* 縮小を許可 */
  word-break: break-word; /* 長い単語を折り返す */
}

また、white-space: nowrap はナビゲーションバーやタグリストなどではみ出しの原因になりがちなので注意しましょう。

Grid に関する補足: Grid でも min-width: auto は同様に影響しますが、minmax()、固定トラック、内在サイズ、grid-template-columns などもはみ出しの原因になります。いずれにしても、min-width: 0 は有効な対策です。


9. パフォーマンスとデバッグ

  • box-sizing はレンダリングパフォーマンスに影響しません。
  • レイアウトのはみ出しをデバッグするには、DevTools を開き、対象要素を選択して Computed タブの Box Model を確認します。
  • marginpaddingbordermin-widthwhite-space などが原因かどうか調べます。

10. 実践チェックリスト

  • □ すべての要素に box-sizing: border-box を設定したか?(inherit パターンも検討)
  • width: 100%padding/border を併用する場合、その要素にも border-box を設定したか?
  • □ 親要素が content-boxborder-box かを理解しているか?(親が border-box でなくても問題ないが、計算方法は理解すべき)
  • width: 100%margin を併用する場合、calc() で調整するか、width: auto に変更することを検討したか?
  • □ 画像・動画・iframe には max-width: 100%box-sizing: border-box を設定したか?
  • □ Flexbox/Grid の中で、子要素に min-width: 0 が必要か確認したか? white-space: nowrap が原因になっていないか?
  • □ DevTools で実際のサイズを確認したか?
  • □ 小さいビューポートでのレスポンシブ動作、特に Flex/Grid コンテナをテストしたか?

11. まとめ

  • 問題: padding/borderwidth の外側に追加される(content-box の仕様)ため、width: 100% がはみ出す。
  • 本質: Box Model は content・padding・border・margin からなる。デフォルトでは width は content 領域のみ。
  • 解決策: box-sizing: border-box を使うことで width に padding と border を含める。全体設定が推奨される。
  • 落とし穴: marginwhite-space: nowrap、Flexbox/Grid の min-width: auto などは依然としてはみ出しを引き起こす可能性がある。
  • 常に DevTools で確認し、複数の画面サイズでテストすること。

12. 参考資料


次回予告

👉 【Frontend CSS – パート5】position はブラウザでどう動くのか?Containing Block と座標系を理解する

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?