Flexbox(フレックスボックス)は”Flexible Box(フレキシブルボックス)”の略で、フレキシブルと名前がついているように自由度が高く、HTMLの要素の場所を容易に組み替えることができます。一度Flexboxを使い始めるとあまりの便利際にHTMLの到るところで利用するようによります。しかしFlexboxは設定はシンプルなため十分に理解しないまま使用している人もいるのではないでしょうか。本文書ではFlexboxを使いこなすために必要な情報を一挙に公開しているのでこの機会にFlexboxの基本から使い方までしっかり理解しておきましょう。

FlexboxのほかにGridという機能もあります。こちらも便利は機能なのでFlexboxと一緒にGridの学習も進めて用途に応じて使い分けてください。

Flexboxの2つの要素

Flexboxは、Flexコンテナ(Container)とFlexアイテム(Item)という2つの要素から成り立っていることを理解しておく必要があります。下の図のように親要素であるFlexコンテナの中に子要素のFlexアイテムが入っています。要素間の親子関係がなければ、Flexboxを利用することはできません。

FlexコンテナとFlexアイテムの関係

FlexコンテナとFlexアイテムの関係

具体的なFlexコンテナとFlexアイテムは下記のように親子関係のあるものです。divの場合は、containerクラスの持つ要素が親要素でFlexコンテナ、itemsクラスを持つ要素が子要素のFlexアイテムです。unordered listの場合はulが親要素でliが子要素です。


/* divの場合 */
    <div class="container">
        <div class="items">item1</div>
        <div class="items">item2</div>
        <div class="items">item3</div>
    </div>

/* unordered listの場合 */    
    <ul class="container">
        <li class="items">item1</li>
        <li class="items">item2</li>
        <li class="items">item3</li>
    </ul>

図解:Flexboxの基本機能

Flexboxでは、Direction(方向), Alignment(配置), Wrap(折り返し制御), Order(順番), Size(大きさ)を制御することでレイアウトを調整していきます。

()の内部については、各英単語に対する日本語訳が入っていますが、Wrapについては、包含等の日本語訳では機能が伝わりにくいため、機能の説明である折り返し制御という言葉を使用しています。
fukidashi
  • Direction(方向)
    Flexbox Direction(方向)

    Flexbox Direction(方向)

  • Alignment(配置)
    横方向のFlex Alignment

    横方向のFlex Alignment


    縦方向のFlex Alignment

    縦方向のFlex Alignment

  • Wrap(折り返し制御)
    Flex Wrap(折り返し制御)

    Flex Wrap(折り返し制御)

  • Order(順番)
    Flex Order(順番)

    Flex Order(順番)

  • Size(大きさ)
    Flex Size(大きさ)

    Flex Size(大きさ)

要素をFlexboxとして機能させるためには

Flexboxでは、親子関係を持つ2つの要素が必須となります。その親子関係を持つ要素でFlexboxとして機能させるためには、下記のように親要素のCSSのdisplayプロパティをflexに設定する必要があります。displayをflexに設定するとその要素は、Flexコンテナとなり、その子要素はFlexアイテムとなります。


.container{
   display : flex;
}

初めてのFlexbox

縦に並んだ要素を横並びに変更するという単純な例を使用してFlexboxがどんなものか確認してみましょう。

containerクラスを持つ親要素に3つの子要素が入っているシンプルな構造のHTMLファイルを用意します。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Flexbox</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div class="container">
        <div class="item_1">Flexboxアイテム1</div>
        <div class="item_2">Flexboxアイテム2</div>
        <div class="item_3">Flexboxアイテム3</div>
    </div>
</body>
</html>

各div要素には、それぞれ異なる背景色をつけています。まだ親要素へのFlexboxの設定は行っていません。


.container{
}

.item_1{
    background-color: #f0d9da;
}

.item_2{
    background-color: #c8d9eb;
}

.item_3{
    background-color: #ecf2f9;
}

ブラウザで確認すると3つのdiv要素はブロック要素なので記述した順番に縦に並んで表示されます。

Flexboxの設定なし

Flexboxの設定なし

containerクラスを持つ親要素のdisplayプロパティにflexを設定します


.container{
    display: flex;  
}

親要素のdisplayプロパティをflexに設定しただけで、3つの子要素は縦並びから横並びへと変更していることが確認できます。div要素なので通常は横幅いっぱいに広がるはずですがFlexアイテムになると要素の横幅は中に含まれるコンテンツのサイズになっています。

親要素のdisplayをflexに

親要素のdisplayをflexに

Flexboxの最もシンプルな設定方法が確認できたので、Flexboxの個別の機能を確認していきましょう。

FlexboxのDirection(方向)について

Flexbox Direction(方向)

Flexbox Direction(方向)

FlexboxのDirection(方向)は横並びが初期設定となっています。flex-directionプロパティを使用することで並び方を変更することができます。

flexコンテナである親要素にflex-directionプロパティを追加して値をcolumnに設定します。


.container{
    display: flex;
    flex-direction: column;  
}

flex-directionをcolumnに設定することで縦並びに変更することができます。

flex-directionの設定をcolumn

flex-directionの設定をcolumn

初期設定では横並びになるため指定を行っていませんが、横並びを明示的に設定する場合はrowを設定します。


.container{
    display: flex;
    flex-direction: row;  
}

row, column以外にもrow-reverse, column-reverseがあります。それぞれの設定は図を確認することで簡単に理解することができます。


.container{
    display: flex;
    flex-direction: row-reverse;  
}
flex-directionにrow-reverseを設定

flex-directionにrow-reverseを設定


.container{
    display: flex;
    flex-direction: column-reverse;  
}
flex-directionにcolumn-reverseを設定

flex-directionにcolumn-reverseを設定

FlexboxのAlignment(配置)について

FlexboxのAlignment(配置)は、縦方向、横方向でFlexコンテナ内でのFlexアイテムの配置を変更することができます。そのため、縦方法の配置と横方法の配置では異なるプロパティを持っています。

横方向のAlignment(配置)について

横方向のFlex Alignment

横方向のFlex Alignment

横方向の配置には、justify-contentプロパティを使用して設定を行います。初期設定では、左揃え(flex-start)に設定されています。画面の上部にあるナビゲーションメニューではspace-betweenやspace-aroundを利用します。

その他にも下記の値を設定することができます。

  • flex-start

    初期値。左揃え。

  • flex-end

    右揃え

    
    .container{
        display: flex;
        justify-content: flex-end; 
    }
    
    justify-contentの設定をflex-end

    justify-contentの設定をflex-end

  • center

    中央揃え

    
    .container{
        display: flex;
        justify-content: center; 
    }
    
    justify-contentの設定をcenter

    justify-contentの設定をcenter

  • space-between

    最初と最後の要素が両端、アイテム

    
    .container{
        display: flex;
        justify-content: space-between; 
    }
    
    justify-contentの設定をspace-between

    justify-contentの設定をspace-between

  • space-around

    等間隔

    
    .container{
        display: flex;
        justify-content: space-around; 
    }
    
    justify-contentの設定をspace-around

    justify-contentの設定をspace-around

縦方向のAlignment(配置)について

縦方向のFlex Alignment

縦方向のFlex Alignment

縦方向の配置には、align-itemsプロパティを使用して設定を行います。初期設定では、stretch(親要素の高さ一杯に広がる)に設定されています。

横方向の場合は、親要素がブラウザの横一杯に広がっているため幅の設定を行っていませんでしたが、縦方向の配置を行う場合は親要素に高さを持たせる必要があります。

containerクラスを持つ親要素の高さ150pxを設定します。


.container{
    height:150px;
    display: flex;
}

親要素に高さを設定すると子要素の領域も親要素の高さ一杯まで広がります。高さ一杯まで広がるのは、align-itemsプロパティの初期値がstretchのためです。

親要素に高さ(height)を設定

親要素に高さ(height)を設定

その他にも下記の値を設定することができます。

  • stretch

    初期値

  • flex-start

    初期値

    
    .container{
        height:150px;
        display: flex;
        align-items: flex-start;
    }
    
    align-itemsの設定はflex-start

    align-itemsの設定はflex-start

  • flex-end

    初期値

    
    .container{
        height:150px;
        display: flex;
        align-items: flex-end;
    }
    
    align-itemsの設定はflex-end

    align-itemsの設定はflex-end

  • center

    初期値

    
    .container{
        height:150px;
        display: flex;
        align-items: center;
    }
    
    align-itemsの設定はcenter

    align-itemsの設定はcenter

Flexboxの配置機能で画面中央表示

これまでに説明を行ってきたjustify-contentプロパティとalign-itemsプロパティの設定を行えば、ブラウザ画面の中央に簡単に文字を表示することができます。

h1要素のFlexBox文字列をFlexboxの機能で画面中央に表示させます。親要素は、body、子要素は、h1になり、flexboxは親要素のbodyに設定します。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Flexbox</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>FlexBox</h1>
</body>
</html>

align-itemsを設定するために、body要素の高さは画面いっぱいの100%を設定しています。align-items、justify-contentプロパティどちらもcenterに設定しています。


html,body{
    height: 100%;
}

body{
    display: flex;
    align-items: center;
    justify-content: center;
}

Flexboxの配置機能により、親要素に3つのプロパティを設定するだけで画面中央に文字を表示することができます。

flexboxをブラウザの真ん中

flexboxをブラウザの真ん中

FlexboxのWrap(折り返し制御)について

Flex Wrap(折り返し制御)

Flex Wrap(折り返し制御)

子要素の合計の幅が親要素の幅を超えた場合に、折り返しを行って複数行にするのかそのまま1行のまま表示させるのかを設定するのがflex-wrapプロパティです。初期設定では、nowrapに設定されており、子要素の合計の幅が親要素の幅を超えても複数行にはならず、一行で表示される設定になっています。

親要素の幅がわかるように親要素にborderを設定します。また、子要素の幅をすべて250pxに設定します。


.container{
    border:3px solid red;
    display: flex;
}
.container > div{
    width:250px;
}

親要素の幅が十分あるので、子要素は幅250pxを確保できています。親要素の赤色のborderの中で背景がない部分が余分の領域です。

親要素の幅が子要素の合計より広い

親要素の幅が子要素の合計より広い

親要素の幅を狭めると同時に子要素の幅も狭くなるため、先ほどと変わらず、子要素であるflexアイテムは1行で表示されます。初期設定では、子要素の合計の幅が親要素の幅よりも大きくなったとしても子要素も同じように幅が狭くなることで1行を維持します。

親要素の領域が十分でない場合

親要素の領域が十分でない場合

flex-wrapプロパティを追加し、wrapを設定します。


.container{
    border:3px solid red;
    display: flex;
    flex-wrap:wrap;
}

親要素の幅が十分にないため、3番目の子要素が折り返され、2行になっていることを確認することができます。

flex-wrapの設定をwrapに

flex-wrapの設定をwrapに

さらに親要素の幅を狭めていくと親要素の幅が2つの子要素の幅の合計よりも狭くなるため、すべての子要素が折り返しされ、3行になります。このようにflex-wrapプロパティで折り返しの制御を行います。

親要素の幅をさらに狭める

親要素の幅をさらに狭める

FlexboxのOrder(順番)について

Flex Order(順番)

Flex Order(順番)

Flexboxのflex-directionプロパティでは、row-reverse, column-reverseを設定すると通常の順番とは逆の方向で表示させることができます。Order(順番)では子要素であるFlexアイテム全体ではなく個別に順番の入れ変えを行うことができます。順場の変更には、orderプロパティを使用します。初期設定では0が設定されています。

3番目の子要素を1番最初に表示させたい場合、orderプロパティに”-1″を設定します。


.item_3{
    order:-1;
    background-color: #ecf2f9;
}

初期値である0よりも小さい値である-1を設定したために0が設定されている他の要素よりも先に表示され、プラスの値を設定すると大きいほど後に表示されます。

orderプロパティで順番変更

orderプロパティで順番変更

マイナスの値が大きければ大きいほど前に表示されます。

FlexboxのSize(サイズ)について

ブラウザ上での子要素であるFlexアイテムの幅は、flex-basis, flex-shrink, flex-growの3つのプロパティの組み合わせで行われます。Flexboxの設定で一番わかりにくい箇所で大半の人がここを理解せずにFlexboxを利用しています。Flexboxを使いこなすために重要な設定なので1つ1つのプロパティをしっかり理解していきましょう。

flex-basisプロパティについて

flex-basisでは直接子要素であるFlexアイテムの幅を設定することができます。px等の単位指定でもパーセント%指定でも可能です。初期値はautoで、その要素のコンテンツ幅がFlexアイテムの幅になります。

flex-basisの動作確認を行うために子要素それぞれにflex-basisを使用して幅を設定します。


.container{
    border:3px solid red;
    display: flex;
}

.item_1{
    flex-basis: 150px;
    background-color: #f0d9da;
}

.item_2{
    flex-basis: 200px;
    background-color: #c8d9eb;
}

.item_3{
    flex-basis: 250px;
    background-color: #ecf2f9;
}

flex-basisの指定通りに子要素の幅が表示されています。

flex-basisを設定してFlexアイテムの幅を設定

flex-basisを設定してFlexアイテムの幅を設定

下記のようにflex-wrapを設定し、親要素の幅が子要素の幅の合計より、狭くなった場合の動作をflex-basisでも確認しておきましょう。

親要素にflex-wrapプロパティを追加して、wrapを設定します。


.container{
    border:3px solid red;
    display: flex;
    flex-wrap:wrap;
}

子要素にflex-basisを設定した上で、親要素の幅を狭めていくと、子要素にwidthを設定した時と同様に折り返しが行われることが確認できます。

flex-basisの設定とwrapの設定

flex-basisの設定とwrapの設定

flex-growプロパティについて

子要素の幅の合計よりも親要素の幅の領域が大きい場合、その余った領域をどの子要素に割り当てるかを決めるプロパティです。初期値では、flex-growプロパティの値は0であるため、どの領域にも割り当てられず、余った状態となります。

下の図の親要素のborderの背景色のない部分が余った領域になります。

flex-growの設定が0の場合

flex-growの設定が0の場合

最後の子要素のみに余った領域を与えたい場合は、flex-growプロパティに1を設定します。


.item_3{
    flex-basis: 250px;
    flex-grow:1;
    background-color: #ecf2f9;
}

1つ前の画像と比較するとわかるように余っていた領域が3番目の子要素の領域に組み込まれていることがわかります。

flex-gropを最後の要素に設定

flex-gropを最後の要素に設定

flex-growの数字は、他の子要素に設定したflex-growの数字との相対的な大きさの比較で意味を持つため、1つの要素のみflex-growを設定している場合は、正の数字であれば、2,3などの他の数字にしても結果は変わりません。

次にflex-growの動作を確認するために各子要素に設定していたflex-basisを削除します。


.item_1{
    background-color: #f0d9da;
}

.item_2{
    background-color: #c8d9eb;
}

.item_3{
    background-color: #ecf2f9;
}

flex-basisを削除したことで幅が各要素のコンテンツに依存するようになり、余りの領域が増えています。

flex-basisプロパティを削除

flex-basisプロパティを削除

余った領域を各子要素に均等に割り当てるため、flex-growプロパティの設定を行います。


.item_1{
    flex-grow:1;
    background-color: #f0d9da;
}

.item_2{
    flex-grow:1;
    background-color: #c8d9eb;
}

.item_3{
    flex-grow:1;
    background-color: #ecf2f9;
}

flex-growをすべての子要素に設定することで、余った領域が均等に分配されていることが確認できます。

すべての子要素にflex-grow設定

すべての子要素にflex-grow設定

子要素の2と3に余った領域を与え、その割り合いを1:2に設定したい場合は以下のようにflex-growは1とflex-growは2に設定します。flex-growの数字は、相対的な比較に使用するため、flex-growを3、flex-growを6とした場合も同じ意味を持ちます。


.item_1{
    background-color: #f0d9da;
}

.item_2{
    flex-grow:1;
    background-color: #c8d9eb;
}

.item_3{
    flex-grow:2;
    background-color: #ecf2f9;
}

子要素1の大きさは変わらず、子要素2, 3は1:2の割合で余った領域が分配されていることが確認できます。

flex-growを1:2

flex-growを1:2

flex-shrinkプロパティについて

flex-growでは親要素の余った領域をどの子要素の領域に分配するか設定するプロパティでしたが、flex-shrinkは、親要素が領域が狭まり、子要素の幅の設定値の合計よりも小さくなった場合、どの子要素から不足分の領域をとるかを決めるプロパティです。

例えば、2つの子要素が200pxの領域を持ち、親要素が300pxの領域になった場合、不足した100px分を片方の子要素から100px確保するのかそれとも両方の領域から均等に50px確保するのかを決めるプロパティです。片方の子要素だけからとる場合は、ブラウザの表示では、片方の子要素の幅が100px,もう一方の子要素の幅が200pxで計300pxとなります。両方からとる場合は、子要素の幅はどちらも150pxとなります。

親要素の不足分の領域の子要素での分配

親要素の不足分の領域の子要素での分配

flex-shrinkの初期値は1のため、すべての子要素は均等に縮むことになります。

flex-shrinkがどのような動作をするのか確認してみましょう。すべての子要素の幅をflex-basisを使用して250pxとします。


.container{
    border:3px solid red;
    display: flex;
}

.container > div{
    flex-basis: 250px;
}

.item_1{
    background-color: #f0d9da;
}

.item_2{
    background-color: #c8d9eb;
}

.item_3{
    background-color: #ecf2f9;
}

子要素1,2はflex-shrinkを0に設定し、縮まない設定にします。子要素3の変更は行いません。(初期値は1)


.item_1{
    flex-shrink: 0;
    background-color: #f0d9da;
}

.item_2{
    flex-shrink: 0;
    background-color: #c8d9eb;
}

親要素を狭めていくと子要素の3のみ縮むことが確認できます。

子要素1,2のflex-shrinkは0に設定

子要素1,2のflex-shrinkは0に設定

flex-shrinkを使用して縮む割合の変更を行います。子要素1は0のままで縮まない設定、子要素の2, 3は縮む割合を1:2に設定します。1:2に設定した場合、子要素3の領域は、2の領域よりも2倍の速さで縮むことになります。


.item_1{
    flex-shrink: 0;
    background-color: #f0d9da;
}

.item_2{
    flex-shrink: 1;
    background-color: #c8d9eb;
}

.item_3{
    flex-shrink:2;
    background-color: #ecf2f9;
}

子要素1は縮まない設定を行っているので、子要素2, 3を比較すると1:2の割合で縮んでいることを確認できます。flex-growと同様flex-shrinkの数字も相対値のため、flex-shrinkの値を4と8にしても結果は同じになります。

flex-shrinkの設定値を要素毎に別の値

flex-shrinkの設定値を要素毎に別の値

flexプロパティについて

ここまでflex-basis, flex-grow, flex-shrinkの個別の設定方法について説明を行ってきましたが、それらのプロパティを一括で設定できるflexプロパティがあります。

flexプロパティの設定には、複数の設定方法があります。


/* 数字の値を一つ設定するとflex-growが1に設定される */
    flex: 1;

/* 単位付きの値を一つ設定するとflex-basisが100pxに設定される */
    flex: 100px;

/* 数字の値を2並べるとflex-growが1, flex-shrinkは2に設定される */
    flex: 1 2;

/* 数字と単位付きの値を2つ並べるとflex-growが1, flex-basisは100pxに設定される */
    flex: 1 100px;

flexプロパティを使用して、1:2:1の幅のあるレイアウトを作成したい場合は、下記のように記述すれば簡単に作成することができます。


.container{
    border:3px solid red;
    display: flex;
}

.item_1{
    flex:1;
    background-color: #f0d9da;
}

.item_2{
    flex:2;
    background-color: #c8d9eb;
}

.item_3{
    flex:1;
    background-color: #ecf2f9;
}

ブラウザの幅を広げても、縮めても子要素の幅の割合いは、1:2:1を維持します。

3コラムで1:2:1レイアウト

3コラムで1:2:1レイアウト

1:3:1の比への変更があったとしても子要素2のflexの値を2から3に変更するだけで完了します。


.item_2{
    flex:3;
    background-color: #c8d9eb;
}
3コラムで1:3:1レイアウト

3コラムで1:3:1レイアウト

要素1の幅だけはどんなことがあっても変更しないのであれば、flex-grow, flex-shrinkを0にflex-basisで幅の指定を行えば実現可能です。


.item_1{
    flex:0 0 180px;
    background-color: #f0d9da;
}

Flexboxで、ナビゲーションメニューを作ってみよう

Flexboxの機能を一通り理解できれば、ナビゲーションメニューも簡単に作成することができます。下記の4つのリストから構成されているリストにFlexboxを行い、ナビゲーションメニューを作成します。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Flexbox</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <ul>
        <li><a href="#">トップ</a></li>
        <li><a href="#">会社概要</a></li>
        <li><a href="#">事業内容</a></li>
        <li><a href="#">お問い合わせ</a></li>
    </ul>
    
</body>
</html>

CSSを見ると少し複雑に見えるかもしれませんが、ulタグの初期設定のmarginとpaddingを0にしています。また、リストスタイルをnoneにすることでリストの先頭に表示される・(点)を非表示にしています。aタグにpaddingでクリック領域を増やすためにブロック要素に変換しています。

Flexboxに関する設定は、親要素ulをFlexコンテナにし、子要素の配置はspace-aroundに設定しています。 子要素のliはflexを1(flex-growが1)に設定し、親要素に対して均等に幅を取る設定にしています。


ul{
    margin: 0;
    padding: 0;
    list-style-type: none;
    background-color:beige;
    display: flex;
    justify-content: space-around;
}

li{
    flex:1;
}

li a{
    padding:1em;
    display: block;
    text-align: center;
    text-decoration: none;
    font-weight: bold;
    color:orange;
}

li a:hover{
    background-color: gray;
}

ブラウザで確認すると下記のようなナビゲーションバーを作成することができます。ブラウザの幅を変更しても幅に合わせて子要素間の距離も等間隔で変動します。

flexboxでナビゲーション

flexboxでナビゲーション