Edited at

CSSのflexを使ったリストのスクロール方法

More than 1 year has passed since last update.

CSSのflexという機能を知ってその使い方をメモ的に残しておきます。

flex はタグのスタイルにdisplay: flexを指定することでその子要素の配置を簡単に行う機能です。

詳細な説明は以下のページが図解付きでとてもわかりやすく説明してくださっています。

このflexを使うことでページ中の一部をスクロールさせるようなデザインが簡単にできるようです。

サンプルを以下に作成しました。中央のリスト部分を縦にスクロールできます。

これの具体的な指定内容は以下の通りです。

<div

class="list-container"
style="
width: 200px;
height: 250px;
display: flex;
flex-direction: column;
"
>

<div
class="list-header"
style="
flex-grow: 0; /* 省略可 */
flex-basis: auto; /* 省略可 */
"
>
ヘッダー
</div>

<div
class="list-body"
style="
flex-grow: 1;
flex-basis:  0;
overflow-y: scroll;
"
>
<div class="list-item">リスト1</div>
<div class="list-item">リスト2</div>
<div class="list-item">リスト3</div>
</div>

<div
class="list-footer"
style="
flex-grow: 0; /* 省略可 */
flex-basis: auto; /* 省略可 */
"
>
フッター
</div>
</div>

こういったレイアウトを行う時に問題になるのは、ヘッダーやフッターなどの配置を固定した上で、リスト部分(class="list-body"の部分)のサイズを最大にする方法です。flex を使うことでpx単位で固定の値を使うことなく、このbodyの高さの自動調整を行うことができます。

リスト部分(`class="list-body"`)の高さ = 

一番外側のタグ(class="list-container")の高さ
- (ヘッダーの高さ + フッターの高さ)

設定のポイントは以下のとおりです。


  • 一番外側の領域 (list-container)


    • 高さを指定する


    • display: flex;を指定する


    • flex-direction: column;を指定して中のヘッダー、ボディ、フッターが縦に並ぶようにする



  • ヘッダー、フッター(list-header, list-footer)



    • flex-grow: 0; flex-basis: auto;が設定された状態にして高さが固定になるようにする

    • これはflexの内部要素(flexItem)のデフォルト値なので省略可能



  • ボディ(list-body)



    • flex-grow: 1; flex-basis: 0;を指定して高さを自動計算されるようにする


    • overflow-y: scroll;で内部がはみ出したときにスクロールするように指定する



この指定でのflexによる高さの計算は以下のような理屈のようです。


  1. flexの子要素の初期の高さを算出



    • flex-basis: autoであるためlist-header, list-footerの高さをそのタグの中身から決定する

    • list-bodyの高さを、flex-basis: 0の指定から0pxとする



  2. (list-containerの高さ - Step.1で算出した子要素の高さの合計) = (list-containerの高さ - (list-headerの高さ + list-footerの高さ + list-bodyの高さ(= 0px) )) を算出する

  3. Step.2で算出した高さを、子要素のflex-growの値の比率に合わせて分配する


    • list-headerの高さ : list-bodyの高さ : list-footerの高さ = flex-grow: 0 : flex-grow: 1 : flex-grow: 0 = 0 : 1 : 0

    • つまり、list-bodyにStep.2での高さを全て割りあてる



結果的に、list-bodyの高さ = list-containerの高さ - (list-headerの高さ + list-footerの高さ)が実現されています。