しっかり理解しておくと便利なCSSのテクニック、minmax()関数の使い方
Post on:2020年11月26日
minmax()はCSSの関数で、要素サイズの最小値と最大値を定義することができます。カードを配置するグリッド、記事を中央配置で画像を幅いっぱいにするフルブリードなど、ページのレイアウトやUIコンポーネントの実装に非常に便利です。
CSS Gridにおけるminmax()関数の実用的で、便利な使い方を紹介します。
A Deep Dive Into CSS Grid minmax()
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- はじめに
- CSS Gridにおけるminmax()関数
- minmax()のバリデーション
- minmax()をシンプルなグリッドに使用する
- auto-fitとauto-fillの相違点
- minmax()の便利な使い方
- 考えなしに、auto-fitを使うことの弊害
- 終わりに
はじめに
CSS Gridの初歩的なチュートリアルやガイドはたくさんあり、私も書きました。しかし、ほとんどのチュートリアルで十分な解説と実際の使用例が提供されていないため、minmax()関数に対する誤解があることに気がつきました。
minmax()は非常にパワフルで、便利です。
そのため、minmax()について完全なガイドを解説すれば、役立つと思いました。
この記事では、minmax()を深く掘り下げ、どのように、いつ、なぜ使用するのかを解説します。記事を読み終えた後に、あなたがminmax()を完全に理解することを期待しています。
それでは、はじめましょう!
CSS Gridにおけるminmax()関数
CSSの仕様によると、minmax(min, max)の定義は次のとおりです。
最小(min)以上および最大(max)以下のサイズ範囲を定義します。
簡単にグリッドの列や行の値としてminmax()を使用できます。
基本的な使い方を見てましょう。
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: minmax(200px, 500px) 1fr 1fr; grid-gap: 1rem; } |
minmax()の基本的な使い方
このCSSを解説します。
- 3カラムのグリッドがあります。
- 1列目の幅はminmax(200px, 500px)で、これは最小値に200px、最大値に500pxを定義しています。
- 2列目と3列目の1frは、利用可能な残りのスペースを分配します。
では、異なるビューポートのサイズについて考えてみましょう。
ビューポートのサイズが小さくなるとどうなると思いますか?
簡単に言うと、水平のスクロールバーが表示されます。もちろん、それが意図的に行われたものでない限り、水平のスクロールバーを好む人はいないと思います。
水平のスクロールバーが表示される
つまり、minmax()だけではレスポンシブデザインを扱えない、ということです。
これについては後ほどユースケースのセクションで詳しく解説します。
minmax()のバリデーション
minmax(min,max)のmin値がmax値より大きい場合、max値は無視され、min値のみが使用されます。
500pxのみが使用される
また、min値に1frを使用すると無効になるので注意してください。1frはmax値に対してのみ機能します。これはmin値がmax値より大きい場合よりも悪いことです。宣言全体が無視されます。
min値に1frを使用すると、宣言全体が無効になる
minmax()のmin値に0を使用する
minmax(0, 500px)にするとどうなると思いますか?
幅は最小で0になり、500pxを超えることはありません。つまり、ビューポートの幅が十分ではない場合、列の幅がリサイズされてしまうということです。
min値に0を使用すると、列の幅がリサイズされる
minmax()をシンプルなグリッドに使用する
3カラムのグリッドを作成したいとしましょう。
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr); grid-gap: 1rem; } |
各カラムの最小幅は200pxで、下記のように表示されます。
3列のグリッド
各カラムの幅の定義は同じなので、下記のように記述できると思うかもしれません。
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: repeat(3, minmax(200px, 1fr)); grid-gap: 1rem; } |
repeat()関数を使用することで、minmax()を3回繰り返さないようにしました。
確かに機能しますが、お勧めしません。その理由を解説します。
カラム数を手動で変更する
カラム数を変更する場合は、手動でカラム数を変更する必要があります。私にとっては、それは意味がありません。CSS Gridにはもっと多くの可能性があります!
水平スクロールバーが発生する
カラム数を明示的に定義しているため、ビューポートの幅が小さいとブラウザ側で折り返しをさせることができません。その結果、水平スクロールバーが表示されます。
水平スクロールバーが表示される
水平スクロールバーを修正するにはどうすればよいでしょうか?
ビューポートの幅が十分ではない場合は、カラム数を減らすということをブラウザ側に知らせる必要があります。
Flexboxでは、親要素にflex-wrap: wrap;を追加することで修正できます。
参考: CSS Flexbox の基礎知識と使い方をやさしく解説
1 2 3 4 |
.parent { display: flex; flex-wrap: wrap; } |
上: flex-wrap: wrap;を追加、下: なし
CSS Gridでは、auto-fillまたはauto-fitを追加します。
上: auto-fillまたはauto-fitを追加、下: なし
auto-fitとauto-fillの相違点
上記のような問題を解決するために、auto-fillまたはauto-fitの恩恵を受けることができます。しかし、auto-fillとauto-fitの違いには注意が必要です。
auto-fitはアイテムを拡張して、使用可能なスペースを埋めてくれます。
そして、auto-fillはアイテムを拡張しません。その代わりに、auto-fillはアイテムの幅を変更することなく、使用可能なスペースを確保したままにします。
上: auto-fillを使用した場合、下: auto-fitを使用した場合
auto-fillまたはauto-fitを使用する場合、ビューポートのサイズによっては同じ結果が得られるかもしれません。つまり、ビューポートのサイズを変更しない限りは、その相違点に気がつかないかもしれません。
下記のGIFアニメをご覧ください。
auto-fitとauto-fillの相違点
auto-fitを使用した折り畳み
下記のGIFアニメでは、点線の長方形は追加のスペースを表しています。ビューポートが大きくなると、ブラウザはその長方形を折り畳み、長方形の幅を他のアイテムに分配します。
auto-fitを使用: ビューポートが大きくなると、その幅を他のアイテムに分配
auto-fillの場合、ブラウザの扱いは異なります。ビューポートが大きくなると、アイテムの幅は拡大せず、空のアイテム(点線)が表示されます。
各アイテムの幅は変更されません。
auto-fillを使用: ビューポートが大きくなると、空のアイテムが表示
minmax()がどのように機能するかこれで分かったと思います。次にいくつかの実際のユースケースを見てましょう。
minmax()の便利な使い方
カードのグリッド
カードのグリッド
minmax()でレスポンシブ対応のカードのグリッド(ラッパー)を作成するのは、最も一般的なユースケースだと思います。
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-gap: 1rem; } |
CSS Gridを学び始めたばかりの頃、このユースケースでgrid-template-columnの値を決めるのは難しいものでした。ビューポートが250px未満だと、水平スクロールが表示されてしまうことに注意しておいてください。
ビューポートが250px未満だと水平スクロールが表示されてしまう
この水平スクロールを解決するには、2つの方法があります。
1つ目はメディアクエリを使用することです。grid-template-columnsを1frにし、ビューポートの幅が十分に大きい場合はminmax()に変更します。
1 2 3 4 5 6 7 8 9 10 11 |
.wrapper { display: grid; grid-template-columns: 1fr; grid-gap: 1rem; } @media (min-width: 300px) { .wrapper { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } } |
2つ目の解決方法は、CSSの比較関数を使用することです。この方法は最新のものなので、使用する前にブラウザのサポートを確認する必要があります。
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); grid-gap: 1rem; } |
minmax()の最小値にmin()関数を使用しています。これは以下の通りです。
- ビューポートの幅が250px未満の場合、minmax()関数の最小値は親の幅の100%になります。
- ビューポートの幅が250px以上の場合、minmax()関数の最小値は250px
少ないCSSでより良い解決方法が実現できました。
CSSの比較関数について詳しく知りたい人は、以下の記事をご覧ください。
コンテンツのラッパーにch単位を使用する
minmax()の便利なユースケースは、記事のレイアウトを実装するために使用することです。この例では、コンテンツは水平方向の中央に配置されています。
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: minmax(1rem, 1fr) minmax(auto, 70ch) minmax(1rem, 1fr); grid-gap: 1rem; } |
最初と最後のカラムは溝として機能し、真ん中のカラムにコンテンツが配置されます。minmax(auto, 70ch)が定義されていることに注目してください。つまり、このカラムの最大幅は1行あたり70文字となります。この文字数は読みやすくするための理想的な文字数です。
最初と最後のカラムは溝、真ん中にコンテンツ
また、最初と最後のカラムは最小幅1remで折り畳まれるため、スマホでも非常に効果的です。
スマホでの表示
この実装方法を詳しく知りたい人は、以前の記事をご覧ください。
考えなしに、auto-fitを使うことの弊害
auto-fitを使いたくなることがあるかもしれません。注意点は、コンテンツが動的であり、実装側で制御できない場合、問題が発生する可能性があることです。
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); grid-gap: 1rem; } |
例えば、4カラムだと美しく見えるカードのグリッドがあるとします。しかし、カードが1枚しかない場合は、残りの使用可能なスペースを埋めるように拡張されます。
4カラムだと美しく見えるグリッド
ぱっと見、問題ないように見えるかもしれませんが、これは良くありません。
その理由は、カードコンポーネントにテキスト付きの画像がある場合、画像も全幅に拡大されてしまうからです。これは期待通りの表示ではありません。
画像が全幅に拡大されてしまう
auto-fitによる弊害が見えてきましたか?
auto-fitは仕様を理解してから使用してください。画像がなければ、使用してもいいかもしれません。しかし、実装するコンポーネントに画像が配置される可能性がある場合は、使用をお勧めしません。
終わりに
CSSのデバッグに関する電子書籍を書いていることをお知らせします。
興味がある場合は、debuggingcss.comにアクセスして、本に関する最新情報を購読してください。
コメントや提案があれば、@shadeed9までお願いします。
sponsors