見出し画像

【CSS】 フレックスボックスとグリッドレイアウトについて改めて考えてみる

この記事では一昔前の方法にも触れつつ、なんとなくやっていた『フレックスボックス、グリッドレイアウトの使い分け』を改めて文章にしてみようと思いました。

昔の手法

float で横に並べる

最近はあまり使わなくなった手法ですが、一昔前のサイトの修正などで見かけることはあるかもしれません。
float とは、『 要素を指定の方向に浮かせる』プロパティです。多少不具合はあったのですが IE6 でも使え、長らく横並びはこれが主流でした。

display で横に並べる

display: inline-block で横に並べる場合、float とは少し挙動が違います。
inline-block というのは img タグのような『 block のように幅や高さを持つ』が、『空間があれば inline のように横に並ぶ』といった性質があります。
float は横に並ぶ要素に指定した left , right でどちらかに寄るのに対し、display: inline-block は親要素の text-align プロパティの値によって寄る方向が決まります。

display と float の使い分け

display であれば、親要素の text-align プロパティで寄せる方向を指定するのに対し、float は子要素に対して指定します。
中央寄せを実装したい場合、display であれば text-align: center; を指定するだけですが、float であれば親要素の横幅を計算して指定することで中央寄せするしかなく、可変に対応するのも大変なので不向きです。

逆にfloatは左右バラバラに寄せることができますが、display で並べる場合は親要素に一括で方向を指定するため不可能です。


最近の手法

CSS Flexible Box Layout Module(フレックスボックス)

以下、フレックス。
並べたい要素の親要素に diplay: flex をつけることで、子要素を横に並べることができます。
diplay: flex がついている要素をフレックスコンテナ、その子要素をフレックスアイテムと呼びます。
色々な指定が可能で、親要素に指定できることや子要素に指定できること、よく使いそうなものを紹介します。

フレックスボックスのイメージ

親要素に指定できること

このフレックスコンテナ内のルールを指定します。
justify-content の flex-start と start は基本的に同じものですが、 start は gridとも共通で使えるのでこっちを使ったほうが良いと思います。
よく使うものだけ抜粋します。

// フレックスの宣言
display: flex;

// 水平方向
justify-content: start; // 左揃え[初期値:flex-start]
justify-content: end; // 右揃え
justify-content: center; // 中央揃え
justify-content: space-between; // 両端揃え

// 垂直方向
align-items: start; // 上揃え[初期値 : flex-start]
align-items: end; // 下揃え
align-items: center; // 中央揃え

// 折り返しの有無
flex-wrap: nowrap; // 折り返さない[初期値]
flex-wrap: wrap; // 折り返す

// 子要素間の逃げ幅の指定
gap: 0; // 要素間の逃げ幅を0pxにする[初期値]
gap: 10px 15%; // 要素間の垂直方向10px、水平方向15%

// 並べる方向の指定
flex-direction: row; // 最初から最後への横並び[初期値]
flex-direction: row-reverse; // 最後から最初への横並び
flex-direction: column; // 最初から最後へ縦並び
flex-direction: column-reverse; // 最後から最初へ縦並び

子要素に指定できること

このフレックスコンテナ内のルールが指定されていても、例外としてフレックスアイテム個々の振る舞いを変えます。
よく使うものだけ抜粋します。

// 垂直位置を変える
align-self: auto; // 親要素のalign-itemsを継承[初期値]
align-self: start; // 左揃え
align-self: end; // 右揃え
align-self: center; // 中央揃え

// 要素の並び順を変える。数値が小さい方が前に並ぶ。
order: 0; // [初期値]

// 拡縮関連のプロパティ
// flex(flex-grow, flex-shrink, flex-basis)をまとめて指定できるショートハンド
flex: 1; // 余剰を均等に伸率。普段はほぼこれしか使わない。

CSS Grid Layout(グリッドレイアウト)

以下、グリッド。
親要素に display : grid; をつけることで、子要素をレイアウトすることができます。親要素でレイアウトを作り、子要素をそこにあてはめていくイメージです。

グリッドレイアウトのイメージ

親要素に指定できること

どのような枠を作るかを設定し、アイテムの寄りなども決めます。
トラックサイズの設定や名前をつけることも可能です。
よく使うものだけ抜粋します。

// グリッドを宣言
display:grid;

// 要素のトラック内での垂直方向の振る舞い
align-items: stretch; // [初期値] トラックサイズまで伸びる
align-items: start; // トラック内で上寄せ
align-items: center; // トラック内で中央寄せ
align-items: end; // トラック内で下寄せ

// 要素がコンテナーより小さい時、水平方向に関してトラック内のどこに置くかの指定
justify-content: start; // [初期値] 左寄せ
justify-content: center; // 中央寄せ
justify-content: end; // 右寄せ
justify-content: space-between; // 両寄せ
justify-content: space-around; // 要素の左右にマージンをつけたような挙動で等間隔
justify-content: space-evenly; // 外側も同じだけ開けるように等間隔

// グリッドトラック

// 横方向のトラックサイズ
grid-template-columns: 200px 1fr 1fr;

// 縦方向のトラックサイズ
grid-template-rows: 1fr 2fr 1fr;

// 上記2つのショートハンド (grid-template-rows / grid-template-columns)
grid-template: 1fr 2fr 1fr / 200px 1fr 1fr;

// エリアに名前をつける。
grid-template-areas:
    "A A A"
    "B B C"
    "D D C";

// 空いたトラックに戻って配置
grid-auto-flow: dense;

frという単位は他の単位で指定してある部分以外の比です。

例えば、コンテナが 1000px で
"1fr 1fr 2fr"であれば列トラックの比は1:1:2となり、
1fr = 1000 / (1+1+2) = 250 のとなるので "250px 250px 500px" となります。

”500px 1fr 1fr 3fr” あれば列トラックの大きさは、
1fr = (1000-500) / (1+1+3) = 100 となるので "500px 100px 100px 300px" となります。

子要素に指定できること

アイテムの場所、順番などを設定できます。
よく使うものだけ抜粋します。

grid-area: A; // Aの場所に配置

grid-column-start: auto; // 自動で配置[初期値]
grid-column-start: 2; // 2つ目のトラックから開始
grid-column-start: span 2; // トラック2つ分のサイズ

grid-column-end: auto; // 自動で配置[初期値]
grid-column-end: 2; // 2つ目のトラックで終了
grid-column-end: span 2;  // トラック2つ分のサイズ

grid-column: 1 / 4;  // ショートハンド(grid-column-start / grid-column-end)

order: 1; // 順番を変える

サブグリッド (subgrid) について

サブグリッド(subgrid)とは、グリッドで並べた子要素を更にグリッドコンテナとして内側のグリッドと結合することができます。メリットとしては、横並びのコンテンツの量によって高さを揃えることができたりします。table のような動きですね。

しかしこれを Firefox で表示すると、他のブラウザとは違う挙動をします。
ググってもこの不具合の情報が出なかったので追記します。

Google Chrome: 118.0.5993.88
Firefox: 119.0

  ← Chrome | Firefox →

親コンテナについた gap を子コンテナの gap で上書きして打ち消しているのですが、Firefox では完全には打ち消せないようです。今のところ gap での対応は無理そうだったので、フレックスアイテムに margin-top をつけて対応するしかなさそうです。

  ← Chrome | Firefox →

せっかくのサブグリッド、少し不便ですが不具合を頭に入れておけば実務でも使用可能です。


フレックスとグリッドの使い分け

両者の考え方

フレックスの考え方は『アイテムを横に並べて、そのアイテム間のルールを設定する』。display: inline-block による横並びに近い印象を受けました。

グリッドの考え方は『外枠をつくり、そこにアイテムをはめ込んでいく』。扱いやすい table のような印象を受けました。

実務での使い分け

ロゴ一覧のような大きさがまちまちなものを横並びさせるようなときはフレックスが向いてるように思います。中央寄せだったり、同じ行にいくつ並ぶかわからない(増えたり減ったりする可能性がある)場合はフレックスを使っておくと無難でしょう。個々のアイテムの大きさを変える場合、子要素にスタイルを与えます。

反対に、横に並ぶ個数や大きさ(比率でも可)が決まっているタイルのような実装をするときはグリッドの方が向いているように思います。また、テキスト量によってトラックの高さを揃える目的でサブグリッドを使うためにgrid を使うのもありだと思います。

結論としては

慣れるまではどちらを使うべきか迷うかもしれません。実際に修正対応などをしていると、「あれ?これこのままでは実装できなくない??」となって変更することもしばしばありました。どちらを使っても実装できる場合でも、両方の性質を考慮して今後起こりうる修正になるべく柔軟に対応できる手段で実装するといいのではないでしょうか。


■お仕事のご依頼やご相談はお気軽に
エイトビーは、Web制作会社としてテクノロジーとクリエイティブの融合で最適なコミュニケーションを提案・創造し、お客さまやユーザーの皆さま、すべての人が幸せになれることを目指しています。

■採用募集はこちら
エイトビーでは、新しい仲間を募集しています。

この記事が気に入ったらサポートをしてみませんか?