「1次元なら Flexbox, 2次元なら CSS Grid」
のように Flexbox と CSS Grid を使い分けると考えている人は多いのではないでしょうか?
じつは、1次元であっても、中身の文字列等の幅に関係ない(つまり 幅 が hug contents じゃない) 要素が含まれるときには、 Flexbox で書くよりも CSS Grid のほうが簡潔になる場合があります。
たとえば、「左側は幅固定で、右側はあまった幅を埋める (ともに中身に左右されない)」のように領域を左右に分ける場合です。
(CodeSandbox のプレビュー画面のサイズを変化させると、左側領域の幅は変わらず、右側だけが変わっていることが分かります。)
1. Flexbox で実装する
flexbox で実装する場合は、次のように書きます。
.flex-parent {
display: flex;
}
.flex-child-fixed {
flex-basis: 8rem;
flex-shrink: 0;
}
.flex-child-fill {
flex-grow: 1;
}
<div class="flex-parent">
<div class="flex-child-fixed">
幅固定
</div>
<div class="flex-child-fill">
幅可変
</div>
</div>
子要素である .flex-child-fixed, .flex-child-fill それぞれに flex のアイテムとしての設定を書き込むことで幅の調節ができていることがわかります。
それぞれに書かれている flex-shrink: 0, flex-grow: 1 を消したらどうなるでしょうか? CodeSandbox で試してみてください。
flex-shrink: 0 を忘れた場合
左側の固定幅の領域に設定した flex-shrink: 0; を消すと、下の図のように、右側領域に入れた文字列が折り返すときに、幅の不足に反応して左側の領域の幅が縮んで (shrink) しまいます。(flex-shrink のデフォルト値が 1 だからです。)
flex-grow: 1 を忘れた場合
右側の可変で埋める領域に設定した flex-grow: 1; を消すと、下の図のように、右側が広がってくれず、(hug content のまま) 中身の文字列の分の幅しか確保してくれません。
2. CSS Grid を使うと簡単に
CSS Grid を使うと、ぐっと簡単になります。
.grid-parent {
display: grid;
grid-template-columns: 8rem 1fr;
}
見ての通り、親要素に対して「このグリッドは、それぞれ 8rem, 1fr の幅の 2つのカラムがある」と指定するだけです。左右の各領域には何も指定する必要がありません。
"1fr" とは
fr
は、CSS Grid の columns, rows の幅指定に使われる単位です。たとえば、
grid-template-columns: 8rem 2fr 3fr;
と書いた場合には、「一番左のカラムの幅は 8rem, 右側2つのカラムの幅は残った幅のそれぞれ 2/5 と 3/5 を割り当てる」という意味になります。
なので今回使った、 8rem 1fr
は、 「左のカラムの幅は 8rem, 残りすべてを右側カラムに割り当てる」という意味です。
左側の幅を hug content にしたい
「右側は可変だけど、左側は、内容によって幅を決めたい」という場合は、諦めて Flexbox を使うしかないのでしょうか?
いいえ、 max-content を指定すれば可能です。
.grid-parent {
display: grid;
grid-template-columns: max-content 1fr;
}
まとめ
今回はこれ以上解説しませんが、 max-content だけでなく、 CSS Grid はかなり柔軟にカラム幅を制御する仕組みを持っているので、ぜひ1次元レイアウトでも CSS Grid で実現できるか試してみてください。