【CSS】タイルレイアウト 左右中央寄せ&折り返し要素を左揃えにする方法

早速ですが、横並びにレイアウトしたい場合、flexboxをよく使う方多いのではないでしょうか?
私自身もその一人です。便利ですよね。

flexboxで左右中央寄せしたい場合、justify-content: center;を指定するだけで実現することができます。

がしかし、ここで困ったことがあります。
flexboxの子要素が折り返した際、justify-content: center;だと折り返した要素も中央揃えになってしまうのです。
この記事にたどり着いたみなさんもこれに悩んでいるのではないのでしょうか?

さぁどうする…

まず、結論からいうと、flexboxで折り返す要素を左揃えにするのは….
出来なくもないですが大変です。flexboxを指定した要素の幅や子要素の幅をしっかりコントロールすればいけなくもないです。

その際は、justify-content: center;だと無理なのでcenterではなくflex-startを指定します。
例えばビューポート幅がこの時は2列にしたいから、子要素の幅は50%(例えば実際は要素間の幅を指定したりするのでこんな単純な値にはならないでしょう)で。このビューポート幅の時は4列にしたいから25%で、みたいな感じでいちいち指定していく感じですね。

正直めんどくさいですよね。
書いていてもめんどくさいなぁと思ったので別の方法を紹介します。

簡単な方法ありますよ

じゃあどうするかという話ですが、なんと CSS Grid を使えば簡単に設定できてしまいます(flexbox を使うのは早々に諦めましょう。モダンなブラウザなら問題なく表示されますよ!)

CSS Grid はあまり馴染みのない方も多いかもしれませんがこの機会に使ってみましょう!

grid 最高です

早速ですがデモを用意してみました。

See the Pen タイルレイアウト 中央寄せ 左揃え(grid) by Ex-365 (@excreative) on CodePen.

なんとこちら、重要なのは以下のたった2行です。

display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

grid を指定した要素の左右の margin を auto にして中央寄せに。
あとは上のプロパティを指定すれば横並びになり、折り返し要素を左揃えにすることができてしまいます。
何を flexbox で悩んでいたんだ、って感じですよね。

それでは細かく見てみましょう。

各要素の解説

grid-template-columns

列のトラックを確保することができ、分割したい列数分の幅を、スペースで区切って指定することができます。
例えば、3列のトラックを確保したい場合は以下のように指定します。

grid-template-columns: 100px 150px 200px;

また、同様に行に対して指定する場合はgrid-template-rowsを使用します。

repeat

grid-template-columnsgrid-template-rowsの中で使うことができる関数です。列や行の繰り返しパターンをコンパクトに記述することができます。

repeat()関数は2つの引数を取ります。
第1引数は「反復回数」、第2引数は「トラック」です。

repeat(反復回数, トラック)

・反復回数

トラックを繰り返す回数を指定します。
指定できる値は1以上の整数値、もしくはauto-fillauto-fitです。

・トラック

繰り返されるトラックの組み合わせを指定します。
下の例でいうと、1行が 20px 60px 20px 60px という組み合わせで繰り返していく事になります。

grid-template-columns: repeat(2, 20px 60px);

auto-fit

repeat()関数の第1引数に指定することができる値です。似た値にauto-fillがあります。どちらも似ていて、反復回数をビューポートのサイズに応じて変化させたい場合に使用します。グリッドコンテナ(親要素)を狭めた際はオーバーフローさせないようにグリッドアイテム(子要素)を折り返してくれます。

auto-fitauto-fillの違いは、グリッドコンテナ(親要素)が広がって1行になった時で、かつminmaxを使用している時に挙動が変わってきます。

余白(隙間)が生まれた際、auto-fitはグリッドアイテムが全てを埋めようとできるだけ大きくなるようにふるまうのに対して、auto-fillはグリッドアイテムの幅分のスペースが生まれると、そこに新たな空のグリッドを生成しできるだけ小さくなろうとします。

minmaxを使用せずに、repeat(auto-fill, 80px)のような固定値を指定した場合や、折り返して2行以上になっている時は、auto-fitとauto-fillは全く同じ挙動になります。

See the Pen Untitled by Ex-365 (@excreative) on CodePen.

minmax

CSS Gridで使用される関数です。
第1引数にmin(最小値)、第2引数にmax(最大値)を指定します。
もし、min が max より大きい場合は無視され、minmax(min, max)は min として扱われます。
また、1frのような<flex>値はmaxのみで機能しますので注意が必要です。

下の例だと、ビューポートが狭くなった時にも、1列目は最低200pxは確保され、2列目3列目の1frは残りのスペースを分配します。

grid-template-columns: minmax(200px, 400px) 1fr 1fr;

上記の例だと、ビューポートが狭くなっても折り返さない。つまりminmax()だけではレスポンシブデザインでは扱うことができないので注意が必要です。(auto-fill, auto-fit と組み合わせて使用する必要があります。)

See the Pen Untitled by Ex-365 (@excreative) on CodePen.

まとめ

CSS Grid はうまく使えればかなり便利そうですね!
今回はまだ氷山の一角ですので、機会があれば別の使い方も紹介できればと思います。

それではまた!