要素の並列レイアウト制御 – display flex
(※ 当ページは社内技術資料としての位置付けですので読みにくいこともあるかもしれませんが、一般の方の課題解決に役立てれば幸いです。)
目的
グロナビメニュー項目や左右二段組などで、html要素を並列レイアウトにしたいことがあります。
並列レイアウトを実現するには以下の方法があります。
- float
- inline-block
- table
しかしながらこれらの方法では、レイアウトの変更やレスポンシブのような動的な動作への対応が非常に難しくなってしまいます。
対策
フレックスボックスを使用するのがおすすめです。html構成を変更することなく、cssだけで様々なレイアウトへの変更制御が可能になります。
HTML
1 2 3 4 5 |
<ul> <li>1番目の要素</li> <li>2番目の要素</li> <li>3番目の要素</li> </ul> |
CSS
1 2 3 4 |
ul{ display: -webkit-flex; display: flex; } |
親要素に指定すると、子要素が並列レイアウトになります。
バリエーション
(※ 以下の例でのcssはフレックスボックスに関連する必要最低限の記述にとどめています。)
1 均等両端揃え
HTML
1 2 3 4 5 |
<div class="wrapFlex"> <div class="par">領域1</div> <div class="par">領域2</div> <div class="par">領域3</div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-justify-content: space-between; justify-content: space-between; } .par{ -webkit-flex-basis: 30%; flex-basis: 30%; } |
2 可変要素数での均等両端揃え
要素数が一定でない場合に均等横並びにするには、親要素に「flex-wrap: nowrap;」、子要素に「width: 100%;」としておくと簡単に制御できます。
flex-basis が指定されている場合は解除「flex-basis: auto;」しておいてください。
HTML
1 2 3 4 5 6 |
<div class="wrapFlexNowrap"> <div class="par2">領域1</div> <div class="par2">領域2</div> <div class="par2">領域3</div> <div class="par2">領域4</div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 |
.wrapFlexNowrap{ display: -webkit-flex; display: flex; -webkit-flex-wrap: nowrap; flex-wrap: nowrap; -webkit-justify-content: space-between; justify-content: space-between; } .par2{ flex-basis: auto; width: 100%; } |
3 固定+可変
HTML
1 2 3 4 |
<div class="wrapFlex"> <div class="fix">固定領域</div> <div class="var">可変領域</li> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-justify-content: space-between; justify-content: space-between; } .fix{ -webkit-flex-basis: 200px; flex-basis: 200px; margin-right: 30px; } .var{ -webkit-flex: 1; flex: 1; /*(※1)*/ } |
(※1)「flex-grow: 1;」とすると、可変領域側の内容が最大幅を超えたときに、固定領域側が固定ではなくなってしまうようです。この時親側に「flex-wrap: wrap;」があると改行してしまいますので、ご注意ください。
4 縦並び
ここで「flex-wrap: wrap;」を追加しておくと、子要素の幅の合計が親要素の幅を超えたときに改行して配置するようになります。この性質を利用して、子要素の幅をすべて100%にするとすべて縦並び、50%50%の要素+100%とすると2個が並列で3個目が縦に並ぶというレイアウトが楽にできます。
また、flex-basis: 200px;はdisplay: flex;の固定幅の正式な制御方法ですが、widthを使用しても同じ効果が得られます。widthの方が直感的に解かりやすいのでこちらを使用することにします。
※flex-basisとwidthが同時に指定された場合はflex-basisが優先されるようです。解除は「flex-basis: auto;」とします。
HTML
1 2 3 4 |
<div class="wrapFlex"> <div class="fix">固定領域</div> <div class="var">可変領域</div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: space-between; justify-content: space-between; } .fix{ width: 100%; margin-right: 0px; } .var{ -webkit-flex: 1; flex: 1; } |
5 要素入れ替え
並列要素を入れ替える場合は親要素に「flex-direction: row-reverse;」を指定します。
下の例では固定要素が左に配置されていた時に入れていた右スペースを、左に入れ替えています。
下の例ではブラウザの幅を480px以下にしたときに縦列レイアウトに変化します(レスポンシブ動作)。
縦列レイアウトへのレスポンシブ制御は、固定要素をwidth:100%;とし、固定要素が右に配置されていた時に入れていた左スペースなくしています。これはflex-wrap: wrap;としていることで実現される動作です。
さらに縦列要素を入れ替える場合は親要素に「flex-direction: column-reverse;」を指定します。
HTML
1 2 3 4 |
<div class="wrapFlex reverse"> <div class="fix">固定領域</div> <div class="var">可変領域</div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: space-between; justify-content: space-between; } .reverse{ -webkit-flex-direction: row-reverse; flex-direction: row-reverse; } .fix{ width: 200px; margin-left: 30px; margin-right: 0px; } .var{ -webkit-flex: 1; flex: 1; } @media only screen and (max-width: 480px) { .fix{ width: 100%; margin-left: 0px; margin-right: 0px; } .reverse{ -webkit-flex-direction: column-reverse; flex-direction: column-reverse; } } |
利用シーンが多いパターン
1 複数要素の一列並列レイアウトからのレスポンシブでの複数列並列数変更
HTML
1 2 3 4 5 6 7 8 |
<div class="wrapFlex"> <div class="par">領域1</div> <div class="par">領域2</div> <div class="par">領域3</div> <div class="par">領域4</div> </div> <p class="mb0">CSS</p> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: space-between; justify-content: space-between; } .par{ width: 23%; } @media only screen and (max-width: 480px) { .par{ width: 48%; } } |
2 固定+可変の並列レイアウトからのレスポンシブでの縦列レイアウトへの変更
HTML
1 2 3 4 |
<div class="wrapFlex"> <div class="fix">固定領域</div> <div class="var">可変領域</div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
.wrapFlex{ display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: space-between; justify-content: space-between; } .reverse{ -webkit-flex-direction: row-reverse; flex-direction: row-reverse; } .fix{ width: 200px; /* margin-left: 30px; /* */ margin-right: 30px; } .var{ -webkit-flex: 1; flex: 1; } @media only screen and (max-width: 480px) { .fix{ width: 100%; margin-left: 0px; margin-right: 0px; } .reverse{ -webkit-flex-direction: column-reverse; flex-direction: column-reverse; } } |
.reverseを親要素に指定すれば、入れ替えが簡単に実現できます。
さらに詳しくは
下記サイトが詳しいですので参考にしてください。
CSS Flexboxチートシート
CSSフレックスボックス(display:flex)の使い方