この記事で解決できること
- 画面幅を縮小したときに右側に謎の隙間ができる
- 横スクロールバーが勝手に表示される
overflow-x: hiddenで隠しても根本解決しない
レスポンシブ対応したはずなのに、なぜか特定の画面幅で右側に隙間が出る——Web制作をしていると、一度は遭遇するこの問題。今回は実際のクライアントワークで遭遇した事例をもとに、原因の特定方法から根本的な解決策までを解説します。
発端:「スマホで見ると右に隙間があるんですけど…」
先日、建設会社のコーポレートサイトをリニューアルしていたときのことです。
PC版の確認を終え、いざレスポンシブチェック。Chrome DevToolsで画面幅を縮小していくと……
「あれ、右側に白い隙間がある?」
画面幅1200px以上では問題なし。しかし1100px付近まで縮小すると、ページ全体の右側に10〜20pxほどの隙間が出現し、横スクロールバーまで表示されてしまいます。
レスポンシブ対応はしっかりやったはず。メディアクエリも適切に設定したはず。なのに、なぜ?
最初にやった「間違った対処法」
焦った私は、まず以下のCSSを追加しました。
|
1 2 3 |
body { overflow-x: hidden; } |
横スクロールを無効化すれば、隙間も見えなくなるだろう——そう考えたのです。
結果、横スクロールバーは消えました。しかし、隙間自体は残ったまま。ページ右端に謎の余白があり、フッターのリンクが見切れてしまっています。
これは対症療法であって、根本解決ではありません。「はみ出している要素」を特定して修正しなければ、いつまでも問題は残り続けます。
犯人探し:どの要素がはみ出しているのか?
方法1:セクションごとに display: none する
地道ですが、最も確実な方法です。
|
1 2 3 4 5 |
/* 怪しいセクションを順番に非表示にしてテスト */ .header { display: none; } /* → 隙間あり */ .hero { display: none; } /* → 隙間あり */ .main-content { display: none; } /* → 隙間あり */ .footer { display: none; } /* → 隙間が消えた! */ |
今回はフッターを非表示にしたときだけ隙間が消えたので、犯人はフッター内のどこかにいることが確定しました。
方法2:Chrome DevToolsで視覚的に確認する
DevToolsの「Elements」タブで要素を選択すると、その要素のボックスが画面上でハイライトされます。
フッター内の .footer-nav-sections-grid を選択したところ、ボックスが画面の右端をはみ出していることが視覚的に確認できました。
原因の深掘り:なぜフッターがはみ出すのか
フッターの構造を見てみましょう。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<footer class="footer"> <div class="footer-container"> <div class="footer-header-row"> <!-- 左側:ロゴ + 会社名 --> <div class="footer-header"> <img src="logo.svg" alt="ロゴ"> <p>株式会社サンプル建設</p> </div> <!-- 右側:ナビゲーション --> <div class="footer-right-section"> <div class="footer-nav-sections-grid"> <!-- 6つのナビゲーション(3列×2行) --> </div> </div> </div> </div> </footer> |
そして、問題のCSSがこちらです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
.footer-header-row { display: flex; } .footer-header { min-width: 360px; margin-right: 40px; flex-shrink: 0; /* ← 問題その1 */ } .footer-right-section { flex: 1; } @media (max-width: 1200px) { .footer-nav-sections-grid { grid-template-columns: repeat(3, 200px); /* ← 問題その2 */ gap: 24px; } } |
問題その1:flex-shrink: 0 の罠
flex-shrink: 0 は「このボックスは絶対に縮小させない」という指定です。
これが設定されていると、親要素の幅が足りなくなっても縮小してくれません。画面幅が狭くなっても、ロゴエリアは頑なに360px以上を確保し続けます。
問題その2:固定幅のグリッドカラム
grid-template-columns: repeat(3, 200px) は「200pxのカラムを3つ作る」という指定です。
これにより、グリッドの最小幅は常に以下の値になります。
|
1 |
200px × 3列 + 24px × 2(gap)= 648px |
どんなに画面が狭くなっても、このグリッドは648px以下には縮小しません。
数値で見る「はみ出しの瞬間」
実際に計算してみましょう。
画面幅1150pxの場合
| 要素 | 幅 |
|---|---|
| コンテナ内幅 | 1150px − 40px(padding)= 1110px |
| フッターヘッダー(左) | 400px(flex-shrink: 0で固定) |
| 右セクション用の残り | 1110px − 400px = 710px |
| グリッドが必要な幅 | 648px |
710px > 648px なので、ギリギリ収まります。
画面幅1080pxの場合
| 要素 | 幅 |
|---|---|
| コンテナ内幅 | 1080px − 40px = 1040px |
| フッターヘッダー(左) | 400px(縮小しない) |
| 右セクション用の残り | 1040px − 400px = 640px |
| グリッドが必要な幅 | 648px |
640px < 648px で、8pxはみ出しました!
この「8pxのはみ出し」が、右側の隙間の正体です。
解決策:固定幅を「柔軟な幅」に変える
解決策1:flex-shrink: 0 を削除する
|
1 2 3 4 5 |
.footer-header { min-width: 360px; margin-right: 40px; /* flex-shrink: 0; を削除 */ } |
これにより、フッターヘッダーが必要に応じて縮小できるようになります。ただし、ロゴが極端に小さくなる可能性があるため、min-width は残しておくのがおすすめです。
解決策2:固定幅グリッドを minmax() に変更する
|
1 2 3 4 5 6 7 |
@media (max-width: 1200px) { .footer-nav-sections-grid { /* Before: repeat(3, 200px) */ grid-template-columns: repeat(3, minmax(140px, 200px)); gap: 24px; } } |
minmax(140px, 200px) は「最小140px、最大200pxの範囲で柔軟に調整する」という指定です。
これにより、グリッドの最小幅が以下のように変わります。
|
1 2 |
Before: 200px × 3 + 24px × 2 = 648px(固定) After: 140px × 3 + 24px × 2 = 468px(最小) |
画面幅に応じて468px〜648pxの範囲で伸縮するようになり、はみ出しが解消されます。
解決策3:より狭い画面向けに列数を減らす
画面幅がさらに狭くなる場合は、列数自体を減らすのも有効です。
|
1 2 3 4 5 6 7 8 9 10 11 |
@media (max-width: 900px) { .footer-nav-sections-grid { grid-template-columns: repeat(2, minmax(140px, 1fr)); } } @media (max-width: 600px) { .footer-nav-sections-grid { grid-template-columns: 1fr; } } |
修正後の確認
修正後、改めてDevToolsで確認します。
画面幅1080pxでも隙間なし。横スクロールバーも表示されなくなりました。
今回の教訓:固定幅の「合計」を意識する
今回の問題から得た教訓をまとめます。
1. flex-shrink: 0 は本当に必要か考える
「絶対に縮小させたくない」場面は意外と少ないです。
使うべき場面:
- アイコンボタン(クリック領域を確保したい)
- 最小限のロゴサイズを保ちたい
使わなくていい場面:
- テキストを含むコンテンツエリア
- 柔軟にレイアウトしたいナビゲーション
2. 固定幅(px)より柔軟な単位を使う
| 危険な書き方 | 安全な書き方 |
|---|---|
width: 200px |
max-width: 200px + width: 100% |
repeat(3, 200px) |
repeat(3, minmax(140px, 200px)) |
min-width: 360px |
min-width: min(360px, 100%) |
3. 複数の固定幅要素の「合計」を意識する
個々の要素は問題なくても、合計すると親要素を超えることがあります。
|
1 2 3 |
左エリア(400px) + 右グリッド(648px) = 1048px ↓ コンテナ幅1040pxでは収まらない! |
レスポンシブ設計では、常に「最悪のケース」(最も狭い画面幅 × 最も幅を取る要素の組み合わせ)を想定しましょう。
4. ブレークポイントの「境界」をテストする
メディアクエリを max-width: 1200px で設定したなら、1200pxだけでなく1199pxでもテストしてください。
境界値は最も問題が起きやすいポイントです。私は以下の幅で必ずチェックするようにしています。
- 1200px / 1199px(PCとタブレットの境界)
- 768px / 767px(タブレットとスマホの境界)
- 480px / 479px(小型スマホ対応)
おまけ:デバッグに使えるCSS
原因調査時に便利なCSSスニペットを紹介します。
全要素のボックスを可視化
|
1 2 3 |
* { outline: 1px solid red !important; } |
どの要素がどこまで広がっているか、一目でわかります。
はみ出し要素を強制的に収める(調査用)
|
1 2 3 4 |
* { max-width: 100vw !important; overflow-x: hidden !important; } |
これで隙間が消えれば、どこかの要素がはみ出していることが確定します。
怪しい要素を目立たせる
|
1 2 3 |
.suspicious-element { background: rgba(255, 0, 0, 0.3) !important; } |
特定の要素の範囲を視覚的に確認できます。
まとめ
「右側の謎の隙間」問題は、ほぼ100%の確率で子要素が親要素の幅を超えていることが原因です。
チェックリスト:
flex-shrink: 0が不必要に設定されていないか- 固定幅(px)のグリッドカラムがないか
min-widthが大きすぎないか- 複数要素の幅の合計が親を超えていないか
- ブレークポイントの境界値でテストしたか
overflow-x: hidden で隠すのは最後の手段です。まずは原因を特定し、minmax() や % 、vw などの柔軟な単位で根本解決を目指しましょう。
レスポンシブデザインでは「柔軟性」が命。固定値は最小限に抑えることで、どんな画面幅でも破綻しないレイアウトが実現できます。






コメント