こんにちは。スタメンでデザイナー兼フロントエンドエンジニアをしているナガキです。
弊社が提供している「TUNAG」 には(オプションで)ビジネスチャット機能があります。
App版チャット
PC版チャット
ご覧のように、スマホアプリ版は非常にシンプルな画面構成ですが、PC版はひとつの画面内に様々な情報を表示する必要があり、どうしても複雑になりがちです。
そんな複雑で大量の情報を CSS の Flexbox
を利用してレイアウトしています。
今回は「TUNAG」PC版チャットを例に、Flexbox
の便利な使い方をご紹介します。
`Flexbox` とは
Flexible Box Layout Module
のことで、Flex Container
と呼ばれる親要素と Flex Item
と呼ばれる子要素を使って、柔軟なレイアウトが実現できます。
CSS Flexible Box Layout - MDN web docs
仕様が何度も変わったり、ブラウザが対応していないなどの問題もありましたが、現在ではほとんどすべてのモダンブラウザで安心して利用することができます。
最近徐々に利用が広がっている Grid Layout
は2次元のレイアウトを定義しますが、Flexbox
は1次元、つまり横か縦、どちらか一方向だけのレイアウト(並びや余白)を定義します。
これだけ聞くと Grid Layout
のほうが便利なように思えますが、Flexbox
をうまく活用することで、その名のとおりフレキシブルなレイアウトが実現できます。
それでは早速、実際のチャット画面を参考にしながら、どのように Flexbox
を利用しているか説明していきましょう。
固定幅 + 可変幅の横方向カラムレイアウト
PC版チャットのベースレイアウトは
位置 | コンテンツ | 横幅 | ウィンドウサイズによる拡縮 |
---|---|---|---|
左 | ルーム一覧 | 固定 | なし |
中央 | 選択中ルームのメッセージ一覧 | 可変 | あり |
右 | 選択中ルームに関する情報 | 固定 | なし |
となっており、左右のカラムが固定幅、中央のメッセージ一覧部分だけがウィンドウ幅にあわせて変わります。
これを CSS で実装しようとすると以下のようになります。
See the Pen flexbox sample 1 by ngk works (@ngk-works) on CodePen.
`flex` プロパティでカラムの拡縮をコントロールする
ポイントとなるのは子要素の flex
プロパティ。これでカラム幅の拡縮の有無(flex-grow
, flex-shrink
)や基準幅(flex-basis
)をまとめて設定しています。
flex: flex-grow flex-shrink flex-basis;
サンプルでは左右のカラムを 100px
の拡縮しない要素とすることで、中央のカラム幅だけがウィンドウ幅に応じて変わるようになります。
このように Flexbox
を利用することで、複数カラムのレイアウトが簡単に実現できました。
固定幅 + 可変幅の縦方向カラムレイアウト
Flexbox
は横方向だけでなく、縦方向にも利用できます。
例えば、左カラムにあるチャットルーム一覧部分のレイアウトを見てみると、
コンテンツ | 高さ | ウィンドウサイズによる拡縮 | スクロール |
---|---|---|---|
ヘッダ(タイトル) | 固定 | なし | なし |
検索フォーム | 可変(なりゆき) | なし | なし |
ルーム一覧 | 可変(なりゆき) | あり | あり |
となっています。
先程のベースレイアウトと比べると、
- コンテンツが並ぶ方向が縦
- 拡縮はしないが、コンテンツの内容によって幅(高さ)が決まるコンテンツがある
- ウィンドウ幅やコンテンツの内容によって幅(高さ)が変わる
という違いがありますが、これも Flexbox
であれば簡単に実装できます。
See the Pen flexbox sample 2 by ngk works (@ngk-works) on CodePen.
`flex-direction` で並べる方向を指定する
flex-direction
を column
に指定するだけで Flex Item
を縦方向に並べることができます。
また、幅をコンテンツ内容に合わせたい場合は flex-basis
に auto
を指定します。
.flex-container--column { display: flex; flex-flow: column nowrap; // 縦方向に並べる } .component-header { flex: 0 0 60px; // 拡縮なし / 固定幅 } .search-form { flex: 0 0 auto; // 拡縮なし / コンテンツに応じた幅 }
縦方向に並べる場合に気をつけなければならないのは、ウィンドウの高さとコンテンツ量の関係です。 コンテンツ量がそれほど多くなく、ウィンドウ内に収まる場合は問題ありませんが、ウィンドウの高さを超える量のコンテンツがある場合は注意が必要です。
「TUNAG」のチャットでは1画面内にすべての情報を収める必要があるため、チャットルーム一覧部分が画面外に広がっていかないよう
.room-list { overflow-y: auto; }
を指定することで、状況に応じてリスト部分だけをスクロールさせています。
サンプルのウィンドウサイズを変えたり、リストアイテムの数を増減させたりして挙動を確認してみてください。
`Flexbox` を利用して、思い通りのレイアウトを実現する
右カラムにはチャットルームの様々な情報が表示されています。
コンテンツ | 高さ | ウィンドウサイズによる拡縮 | スクロール | 配置 |
---|---|---|---|---|
ルームアイコン | 固定 | なし | なし | 上 |
メンバー一覧 | 可変(なりゆき) | あり | あり | 上 |
ファイル一覧 | 可変(なりゆき) | なし | なし | 下 |
(※ 各コンテンツには、指定幅のヘッダ(タイトル)と実コンテンツが含まれます)
チャットルーム一覧とは
という違いがあります。
flex プロパティを利用してカラム位置をコントロールする
コンポーネントの下寄せ配置は、拡縮可能なコンテンツを利用することで実現します。
See the Pen flexbox sample 3 by ngk works (@ngk-works) on CodePen.
上記のサンプルでは
.members { flex: 1 1 auto; }
により、中央のメンバー一覧部分がウィンドウ領域を埋めるように拡縮するため、ファイル一覧が最低限の高さを確保した状態で、最下部に押しやられます。
`margin` プロパティを利用してカラム位置をコントロールする
また別の手段として、margin
を利用する方法もあります。
例えば、下記のようなメンバー一覧部分が拡縮しない場合であっても、
.members { flex: 0 0 auto; }
margin
を利用することで、下寄せ配置が実現できます。
.files { flex: 0 0 auto; margin-top: auto; }
Flex Container をネストすることでスクロールをコントロールする
「TUNAG」PC版チャットでは、コンテンツの高さがウィンドウの高さを超えた場合にメンバー一覧だけをスクロールさせる必要がありました。
See the Pen flexbox sample 4 by ngk works (@ngk-works) on CodePen.
ポイントとなるのは、.members
が .flex-container--column
の Flex Item
であり、.member-list
の Flex Container
でもある点です(.files
も同様)。
Flexbox
は Flex Container
をネスト(入れ子構造)することができるため、うまく利用すると、
- 拡縮の可否
- スクロールの有無
- 配置(寄せ)
などを自由自在に組み合わせることができます。
サンプルでは、メンバー一覧のリスト部分だけを拡縮・スクロール可能な要素とすることで、1画面に収めつつ、状況に応じてスクロールバーを表示しています。
`Flexbox` で柔軟なレイアウトを
冒頭に
`Grid Layout` のほうが便利なように思えますが、 `Flexbox` をうまく活用することで、その名のとおりフレキシブルなレイアウトが実現できます
といった理由が、前項の 自由自在な組み合わせ にあります。
Grid Layout
はピクセルや割り合いを事前に定義する必要があり、(縦/横)幅が異なるコンテナが混在する場合はレイアウトが難しくなってしまいますが、Flexbox
であれば、ピクセルや割り合いを事前に定義することはもちろん、コンテンツに応じた大きさにもできます。
それらを柔軟に組み合わせることができるため、非常に自由度が高いレイアウトが実現できます。
See the Pen flexbox sample 5 by ngk works (@ngk-works) on CodePen.
レイアウトの実装に困ったら、ぜひ Flexbox
を使ってみてください。