CSS Gridのカラム幅を1frにしたときのワナ!意図せぬ水平スクロールバーが表示されてしまった時の解決方法
Post on:2021年2月12日
水平スクロールバーが表示されないように実装したのに、なぜか表示されてしまう、デベロッパーのあるあるです。横に広がってしまったのはCSSの機能が原因なのか、ブラウザの実装が原因なのか、どのような手順でそれを解決したかを紹介します。
The Minimum Content Size In CSS Grid
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
コンポーネントを実装しているときに、予期しない水平スクロールバーが表示されていることに気がつくことがあります。問題を修正するために何度も試行錯誤するうちに、原因が全く別なところだったことはありませんか?
この記事では、何時間もの試行錯誤を台無しにするかもしれないトリッキーな問題について解説します。CSS Gridのレイアウトに関係しており、私はこれを記事にする価値があると思いました。
解説を始める前に、ますは私のコンテキストを明確にします。
- 仕事の途中で課題に直面しました。疲れていて、他にやるべきこともたくさんあります。
- お腹も空いています。
- 作業中のコンポーネントとは関係がないため、問題の根本的な原因を見逃しがちです。
これらを踏まえて、問題について詳しく見ていきましょう。
実現しようとしているレイアウト
実装のコンテキストを詳しく説明します。
実現しようとしているレイアウトは、下記の通りです。メインセクションの最後に、横スクロール可能なコンテナを実装します。
横スクロール可能なコンテナを設置
予期しない水平スクロールバーが表示される
この横スクロール可能なコンテナを実装したところ、ページ全体に水平スクロールバーがあることに気がつきました。これは予期しないことでした。
水平スクロールバーが表示される、なぜ!
このセクションにはラップなしのdisplay: flex;を定義しているため、コンテンツは同じ行に配置されます。さらに、overflow-x: auto;でx軸でのスクロールを可能にしています。
1 2 3 4 |
.section { display: flex; overflow-x: auto; } |
しかし、これでは期待通りに表示されませんでした。スクロール可能なコンテナの実装方法はこれで間違いないと思うので、私は困惑しました。
検証するためにデベロッパーツールで調べてみたところ、幅が非常に大きいことに気がつきました。スクロール可能なコンテナのせいで、.mainの幅が拡大しています。
.mainの幅がめちゃ広がってる!
え!なんで? この問題を見たとき、私は自問自答しました。
- overflow-x: hidden;の記述を忘れた?
- flexboxが何かおかしい?
この2つを再確認したところ、どちらも問題なく記述されており、期待通りに機能するはずです。
と、そのとき、親要素に定義しているCSS Gridが原因ではないかと思いました。親要素を確認してみると、CSS Gridがレイアウトを壊している原因でした。
このような場合、CSSの機能の問題(つまり特定のコンテキストが原因)であるか、ブラウザの実装に問題があるかのどちらかです。
なぜこの現象が起こったのか
なぜCSS Gridが原因なのか、と考えてしまうかもしれません。CSS Gridのコードを見てましょう。
1 2 3 4 5 6 |
<div class="wrapper"> <main> <section class="section"></section> </main> <aside></aside> </div> |
1 2 3 4 5 6 7 |
@media (min-width: 1020px) { .wrapper { display: grid; grid-template-columns: 1fr 248px; grid-gap: 40px; } } |
grid-template-columns: 1fr 248px;で、.mainには1frの値が定義されています。つまり、全体からサイドバーの248pxとギャップの40pxを引いた使用可能なスペースが与えられます。ここまでは問題ありません。
しかし、グリッドアイテムの最小コンテンツサイズはautoです。つまり、グリッドアイテムは長いコンテンツ(ここではスクロール可能なコンテナ)があるため、幅が拡大してしまう可能性があります。
問題の解決方法
この問題を解決するには、autoではなく、最小固定サイズを定義する必要があることをブラウザに伝えることです。これはminmax()関数で簡単にできます。
参考: しっかり理解しておくと便利なCSSのテクニック、minmax()関数の使い方
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: minmax(0, 1fr) 248px; grid-gap: 40px; } |
上記のCSSで問題は解決されました。
さらに、グリッドアイテムレベルでも解決できます。.main要素に下記のいずれかを加えます。
- min-width: 0;を加える。
- もしくは、overflow: hidden;を加える。
コンテキストに応じて、いずれかの解決方法を使用できます。その際は、副作用に注意してください。特に、overflow: hidden;の場合です。
メインセクションの子要素に装飾的な疑似要素があり、その疑似要素がメインの境界線の外側に配置されているとします。その場合、overflow: hidden;を加えると、その疑似要素がクリップされてしまいます。
装飾的な疑似要素(左のシェアボタン、右下の花)がある例
つまり、実装に応じて最適な解決方法を選択する必要があります。
終わりに
リソース
CSSのデバッグに関する電子書籍を書いていることをお知らせします。
興味がある場合は、debuggingcss.comにアクセスして、本に関する最新情報を購読してください。
コメントや提案があれば、@shadeed9までお願いします。
sponsors