2024.10.25

コーディング

⚪︎列△行みたいに並べて表示させたい時には【grid-template-columns: repeat(auto-fill, minmax(最小の幅, 1fr));】がオススメ

たくさんの要素をバーっと並べて表示させたい時って結構ありますよね。
例えばこのブログのTOPでも記事一覧が並んでいます。

こういう⚪︎列△行の一覧表示みたいなものをスタイリングする時みなさんはどうしているでしょうか?

私はこれに結構頭を悩ませ続けてきました。
いくつもやり方を考えたけど、どれもイマイチな部分が出てきてしまう……。

しかし「あぁこれが一番いいな」って思える方法が見つかったので紹介します。

auto-fillとminmaxの組み合わせが最強

おすすめなのはグリッド表示の中でも列の指定をauto-fillminmaxで指定する方法です。

この指定方法ならば列が何列になろうと、デバイスの幅がいくつであろうがシンプルかつビシッとスタイルが決まります。

自分が前に書いた記事「崩れないページをコーディングする際に気をつけていること」内でも言及しているのですが、固定の数値はなるべく使わないのが汎用性のあるスタイリングには重要だと思います。

その中で「これ以上広いと見辛い」や「これ以下は流石に狭すぎ」をmax-widthやmin-widthで指定してやるとどんな幅にもピッタリとハマるサイズにできます。

.grid {
  display: grid;
  gap: お好きな間隔;
  grid-template-columns: repeat(auto-fill, minmax(お好きな最小幅, 1fr));
}

これだけの記述で冗長なブレークポイントを書く必要なく、どんな幅にも対応できる一覧表示ができました。

ほんとにminmaxという指定方法がナイス過ぎる。

この記事で紹介したかったことはもう終わりなのですが、余談でこれまで私がこのスタイリングに気づくまでの一覧表示のやり方とイマイチだなと思ったところも書いてみます。
特に読む必要はないと思うんですが、これで終わるとちょっと短すぎるかなと思うので……。

個人的にNGだったやり方

  • ※ここから下は過去の迷走の歴史というか愚痴というかそんな感じのものでしかないのでほんとに読まなくても大丈夫です。

上記のスタイリング方法に気づく前から「崩れないページをコーディングする際に気をつけていること」に書いた通り「生の数値を使うことを避ける」や「対称性を持たせる」ことは意識していましたのでアイテムには一様に同じスタイルを当てて、例外を持たせない様にはしていました。

なのでこれに反する方法はNGになります。

grid表示だけど列数をブレークポイントで決める方法。

これは好みもあるかもしれませんが、幅が広がれば広がるほど記述を増やさないといけない普遍性の無さが嫌で私はやってませんでした。

特に(まだgapがない時分)ラッピング要素からアイテムまでの距離がアイテム同士の距離以下の時に【一番上の行のアイテムのmargin-topは0】【行の右端のアイテムのmargin-rightは0】みたいな指定を入れる必要のあるスタイリングをしてようものなら、ブレークポイントで列数が変わるたびにその指定もやり直さなくてはいけません。
これはいけてなさすぎる。

【display:flex;】【flex-wrap:wrap;】でアイテムの幅を固定させる方法

これなら列数を意図的に指定する必要はなく、幅が広がってもその分勝手に列数が増えてくれますが、アイテムの幅を固定するのが「生の数値を使うことを避ける」に抵触するためNG。

デバイスの幅によっては余りの空間ができるのもいただけない。

【前までのやり方】display: flex;

とにかく固定の値を指定するということを回避したかったためdisplay:flex;を指定したラッピング要素の中で、アイテムにはflex-growとmin-widthを指定する方法をとっていました。

ただしこれも曲者で、当初は懸念点が2つありました。

①ラッピング要素とアイテムの間に距離がないデザインの時
②最後の行でアイテムの数が少ない時

①はどういうことかというと

テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

👆こんな風に一覧表示を幅いっぱいに取りたい時です。

これの何が問題かというと、アイテムに単純にマージンをつけると幅いっぱいにならないのです。(両サイドに隙間ができる)

テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

かといって


.item:nth-child(4n + 1) {
	margin-left: 0;
}

.item:nth-child(4n + 5) {
	margin-right: 0;
}

なんて指定をするのはもってのほかです。

列数が変わるたびに指定しないといけないなんて蕁麻疹が出ちゃう。

対称性を持たせる」ことにも抵触します。

仕方がないのでラッピング要素にネガティブマージンを入れることで良しとしていました。

ネガティブマージンもほんとは嫌だったんですけどね……。アイテムのマージンを特定方向だけ変えるよりはマシかなという感じ……。

ただ、この問題はgapの登場で解決しました。gapもマジでありがたい存在です。

②の「最後の行でアイテムの数が少ない時」というのは👇こういう時です。

テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

アイテムの幅を固定値ではなくflex-growで指定している弊害です。

行にパンパンにアイテムが詰まってないと一番下の行のアイテムが広がってしまう。

これは他のサイトを参考に幅の指定だけ一緒で高さを持たないダミーアイテムを入れることで解決させていました。

でもやっぱり表示させない要素を入れておくのは嫌だ……列数が増えればダミーの数も増やさないといけないのも嫌だ……

と全然納得していなかったんですが、総合的にはこれが一番マシなんじゃないだろうかと当初は思っていたわけです。

今思えば、これならラッピング要素はgridにして、アイテムの幅は100%にして、gridの列数だけをブレークポイントで指定する方がマシだったかも。

そんな訳で

grid-template-columns: repeat(auto-fill, minmax(最小の幅, 1fr));

👆この記述を知った時は

これだああああああぁぁぁぁぁ!!!!

と、心の中で叫びました。

もしかしたら実際声に出てたかもしれません。

もしちょっと前の私同様この記述を知らずに、この記事を読んで「これは使える」と思ってくれた方がいれば幸いです。

葉っぱ一号

ここまで読んでいただきありがとうございました

この記事を気に入ったら

葉っぱ一号

葉っぱ一号

おいしいお店を探すのが好きです。おいしいお店のために遠出もしちゃいます。遠出したい衝動のためにおいしいお店を探すのかもしれません。そんなものですよね。

この人が書いた記事を見る >>
カモメのアイコンTOP