【CSS入門】flexboxの基本と使い方をプロがわかりやすく解説!
デザインカンプの見た目通りのWebサイトを作成しても、テキスト量や要素の増加によってレイアウトが崩れることがあります。
「再現度を保ちつつ、レイアウトの崩れない柔軟なサイトを作成することはできないのでしょうか?」
そんなお悩みを今回はCSSプロパティのFlexbox(フレックスボックス)を用いて解決していきます。
Flexboxはレイアウトの設定によく用いられるfloatに比べて、横並び/センター揃え/等間隔配列など、行と列を同時に制御することができる優れもの。
以前まではブラウザによって挙動が違ったりサポートしていなかったりとクロスブラウザによる問題がありましたが、最近ではサポートが進み安定して使用できるようになりました。これから利用頻度が上がっていくだろうFlexboxについて実例を交えてご紹介します。
Flexboxの基本
まず基本の設定からです。
Flexboxコンテナー(親要素)
Flexboxを使うには「Flexboxコンテナー」という親要素の設定が必要です。CSSで「display:flex;」を指定すると定義することができます。
Flexboxアイテム(子要素)
「Flexboxコンテナー」の子要素のことを「Flexboxアイテム」と呼びます。とくにCSSで指定する必要はありませんが、孫要素までは「Flexboxアイテム」に定義されないので注意が必要です。
ここまでで基本の設定は完了。
Flexboxコンテナー(親要素)に指定するプロパティ
親要素につかえるプロパティは以下があります。
flex-direction
アイテムの並び順を指定します。
row | 子要素が水平方向に横並びに配置されます。 |
---|---|
row-reverse | 子要素が水平方向に逆順で横並びに配置されます。 |
column | 子要素が垂直方向に縦並びに配置されます。 |
column-reverse | 子要素が垂直方向に逆順で縦並びに配置されます。 |
flex-wrap
アイテムの折り返しを指定する
wrap | 子要素が折り返します。 |
---|---|
wrap-reverse | 逆順に子要素が折り返します。 |
justify-content
アイテムの水平方向の位置を指定する
flex-start | 左揃えで表示します。 |
---|---|
flex-end | 右揃えで表示します。 |
center | 中央で表示します。 |
space-around | 均等な間隔を空けて表示します。 |
space-between | 両端いっぱいまで均等に間隔を空けて表示します。 |
space-evenly | 子要素と同じサイズを間に設置して表示します。 |
align-items、align-content
アイテムの垂直方向の位置を指定する
flex-start | 子要素を上揃えで配置します。 |
---|---|
flex-end | 子要素を下揃えで配置します。 |
center | 子要素を上下中央揃えで配置します。 |
baseline | ベースラインに揃えて配置します。 |
Flexboxアイテム(子要素)に指定するプロパティ
Flexboxは、揃えるだけではなく子要素(アイテム)に対して使用できる便利なプロパティがあるので大変便利です。
order | 並び順を指定 |
---|---|
flex-grow | 伸び率を指定 |
flex-shrink | 縮み率を指定 |
flex-basis | ベースの幅を指定 |
flex | 伸び率、縮み率、ベースの幅を一括指定 |
order
orderは画面幅によって要素の表示順序を変更したいときに、マークアップを変更せずに順番を変更できます。親要素にflex-directionを指定して逆順での表示も可能ですが、さらに細かく指定できます。
HTML
<div class="item01">左から3番目に表示されます</div> <div class="item02">左から1番目に表示されます</div> <div class="item03">左から4番目に表示されます</div> <div class="item04">左から2番目に表示されます</div>
CSS
.item01 {order: 3;} .item02 {order: 1;} .item03 {order: 4;} .item04 {order: 2;}
次にWebサイトを作るうえでよく登場する定番UIパーツで使い方を紹介していきます。細かい装飾はデザインによって異なるので、サンプルをもとに変更点を加えてください。
Flexboxを使用する定番UIパーツ
定番UIパーツをご紹介いたします。
ヘッダー/ナビゲーション
よく見かけるヘッダーのレイアウトです。
Flexboxコンテナーとアイテムを多く使用して、中央寄せや配置の変更を行っています。
HTML
<header class="header"> <div class="header__logo"> <a href="#"><img src="https://coosy.co.jp/assets/img/common/img_site_logo.svg" alt="COOSY"></a> </div> <nav class="header__menu"> <ul class="nav"> <li class="item"><a href="#">ABOUT</a></li> <li class="item"><a href="#">SERVICE<br> / WORK</a></li> <li class="item"><a href="#">WORK</a></li> </ul> <div class="btn"><a href="#">CONTACT</a></div> </nav> </header>
CSS
.header{ display: flex; align-items: center; justify-content: space-between; /*.header に flex を指定し、. header__logo と .header__menu を横並びにする。それらを両端に配置します。*/ } .header .header__menu { display: flex; align-items: center; /*.header__menuに flex を指定し、.nav と .btn を横並びにする。それらを垂直方向の中央付近にまとめます。*/ } .header .nav { display: flex; border-right: 2px solid #444; margin-right: 30px; /* .navに flex を指定し、子要素を横並びにする。*/ } .header .nav .item { border-left: 2px solid #444; } .header .nav .item a { display: flex; align-items: center; justify-content: center; text-align: center; height: 100%; padding: 0 20px; /* .navに flex を指定し、子要素を横並びにする。各プロパティをcenterにして高さを指定することで中央寄せにしている。*/ } .header .btn a { display: block; text-align: center; margin: 0 auto; padding: 6px 28px; color: #fff; background: #444; box-shadow: 0 3px 5px rgb(0 0 0 / 50%); border-radius: 50px; }
パンくずリスト
親要素で子要素を横並びにしてgapでマージンを一元管理できるため、非常にスッキリとしたCSSになります。
HTML
<ul class="breadcrumb"> <li><a href="#">TOP</a></li> <li><a href="#">SERVICE</a></li> <li><strong>SYSTEM</strong></li> </ul>
CSS
.breadcrumb { overflow-x: auto; display: flex; gap: 0 10px; /* .breadcrumb に flex を指定し、子要素を横並びにする。gapで子要素のマージンを指定する。*/ } .breadcrumb > li:not(:last-child)::after { content: "/"; padding: 0 2px 0 10px; }
カード
記事一覧や実績紹介で使われるレイアウトです。
Flexboxコンテナーとmargin-top: auto;を使用することで、複数行に耐えうる上下間のレイアウトの制御が可能です。
HTML
<ul class="listCard"> <li class="listCard__item"> <a href="#"> <p class="title">タイトル</p> <p class="text">1行想定です。</p> <div class="btn"><span>MORE</span></div> </a> </li> <li class="listCard__item"> <a href="#"> <p class="title">タイトル</p> <p class="text">複数行想定のテキストです。複数行想定のテキストです。</p> <div class="btn"><span>MORE</span></div> </a> </li> <li class="listCard__item"> <a href="#"> <p class="title">タイトル</p> <div class="btn"><span>MORE</span></div> </a> </li> <li class="listCard__item"> <a href="#"> <p class="title">タイトル</p> <p class="text">テキスト</p> <div class="btn"><span>MORE</span></div> </a> </li> <li class="listCard__item"> <a href="#"> <p class="title">タイトル</p> <p class="text">テキスト</p> <div class="btn"><span>MORE</span></div> </a> </li> </ul>
CSS
.listCard { display: flex; flex-wrap: wrap; gap: 20px 20px; /* .listCard に flex を指定し、子要素を横並びにする。wrapで折り返しできるようにする。gapで子要素間にマージンを設ける。*/ } .listCard .listCard__item { width: calc(100% / 3 - 20px); background: #fff; /* width: calc(最大横幅 / 一行に残したい個数 - gapで横に指定した数値);*/ } .listCard .listCard__item a { display: flex; flex-direction: column; height: 100%; padding: 10px 20px 20px; /* .listCard__item に flex を指定し子要素を横並びにしますが、column を指定して子要素に横幅を持たせ改行されないようにします。*/ } .listCard .btn { display: block; text-align: center; margin: auto auto 0; padding: 6px 28px; color: #fff; background: #444; box-shadow: 0 3px 5px rgb(0 0 0 / 50%); border-radius: 50px; /* margin-topに auto を指定することで下揃えになります。*/ }
タブメニュー
タブ1の内容が表示されます。
タブ2の内容が表示されます。
タブ3の内容が表示されます。
タブ部分をFlexboxで形成しています。
デザインによって文字位置を変更することができます。
HTML
<div class="tabContent"> <input id="TAB01" type="radio" name="tab" checked="checked"> <label class="tabContent__label" for="TAB01">タブ1</label> <div class="tabContent__main"> <p>タブ1の内容が表示されます。</p> </div> <input id="TAB02" type="radio" name="tab"> <label class="tabContent__label" for="TAB02">タブ2</label> <div class="tabContent__main"> <p>タブ2の内容が表示されます。</p> </div> <input id="TAB03" type="radio" name="tab"> <label class="tabContent__label" for="TAB03">タブ3</label> <div class="tabContent__main"> <p>タブ3の内容が表示されます。</p> </div> </div>
CSS
.tabContent{ display: flex; flex-wrap: wrap; } .tabContent::after{ content: ""; display: block; width: 100%; height: 0; order: -1; background: #E2BD20; } .tabContent .tabContent__label{ margin-right: 3px; padding: 3px 12px; flex: 1; order: -1; border-radius: 3px 3px 0 0; color: #fff; background: #444; cursor: pointer; } .tabContent .tabContent__label:nth-last-of-type(1){ margin-right: 0; } .tabContent input { display: none; } .tabContent .tabContent__main{ width: 100%; height: 0; overflow: hidden; opacity: 0; } .tabContent input:checked + .tabContent__label{ color: #fff; background: #E2BD20; } .tabContent input:checked + .tabContent__label + .tabContent__main{ overflow: auto; padding: 15px; height: auto; border: 2px solid #E2BD20; transition: .5s opacity; opacity: 1; }
ページネーション
ニュース一覧ページに使われる要素です。
横並びのリストをセンター寄せにして、子要素を上下中央配置にしています。
HTML
<ol class="pagenation"> <li><a href="">前へ</a></li> <li><span>1</span></li> <li><a href="">2</a></li> <li><a href="">3</a></li> <li><span class="extend">…</span></li> <li><a href="">9</a></li> <li><a href="">10</a></li> <li><a href="">次へ</a></li> </ol>
CSS
.pagenation { display: flex; flex-wrap: wrap; justify-content: center; } .pagenation li:not(:last-child) { margin-right: 10px; } .pagenation li a, .pagenation li span { display: block; padding: 12px; line-height: 1; background-color: #fff; border: 1px solid #444; } .pagenation li span { color: #fff; background-color: #444; } .pagenation li span.extend { width: auto; background: none; border: none; color: #444; }
フォーム
定番のフォームもFlexboxで作成することができます。
デザインによってタイトルの位置が異なる場合があるので注意しましょう。
HTML
<form> <dl class="contactForm"> <dt class="contactForm__title"> お名前<span class="required">必須</span> </dt> <dd class="contactForm__item"> <input type="text" name="name"> </dd> <dt class="contactForm__title"> メールアドレス<span class="required">必須</span> </dt> <dd class="contactForm__item"> <input type="text" name="email"> </dd> <dt class="contactForm__title"> お問い合わせ内容<span class="required">必須</span> </dt> <dd class="contactForm__item"> <textarea type="textarea" name="contact"></textarea> </dd> </dl> </form>
CSS
.contactForm { display: flex; flex-wrap: wrap; justify-content: space-between; } .contactForm__title { margin: 14px 0; padding: 7px 0 0; display: flex; align-items: center; align-self: flex-start; justify-content: space-between; width: 250px; } .contactForm__item { margin: 14px 0; width: calc(100% - 250px); } .required { padding: 10px; color: #fff; line-height: 1; background-color: #444; margin: 0 14px; font-size: 11px; } input[type="text"], textarea { display: block; padding: 14px; width: 100%; } textarea { height: 200px; }
テーブルレイアウト
- 社 名
- 株式会社クーシー
- 本 社
- テキスト
- 支 社
- テキスト
- 設 立
- 1999年11月9日
- 資本金
- 2000万円
概要ページに用いられるデザインです。
タイトル部分が固定サイズになっているため、コンテンツ部分でその分の幅を減らす必要があります。
HTML
<dl class="tableBasic"> <dt class="tableBasic__title">社 名</dt> <dd class="tableBasic__main">株式会社クーシー</dd> <dt class="tableBasic__title">本 社</dt> <dd class="tableBasic__main">テキスト</dd> <dt class="tableBasic__title">支 社</dt> <dd class="tableBasic__main">テキスト</dd> <dt class="tableBasic__title">設 立</dt> <dd class="tableBasic__main">1999年11月9日</dd> <dt class="tableBasic__title">資本金</dt> <dd class="tableBasic__main">2000万円</dd> </dl>
CSS
.tableBasic { display: flex; flex-wrap: wrap; justify-content: space-between; } .tableBasic__title { margin: 0; padding: 20px 30px; width: 200px; border-bottom: 2px solid #0277b4; } .tableBasic__main { margin: 0; padding: 20px 30px; width: calc(100% - 200px); border-bottom: 1px solid #6f6f6f; }
Flexboxの使用が適さないレイアウト3選
レイアウトの作成や見せ方の変更になにかと便利なFlexboxですが、適していない使われ方もあります。適していないレイアウト例は以下。
- 連続性・規則性のない構成
- 絶対配置を多用するデザイン
- 子要素が存在しない要素
まとめ
今回はどのサイトでも使われている定番UIパーツにFlexboxを使用して制作してみました。
普段使いしているUIパーツをピックアップしたので、実務にすぐに活かせるものがあると思います。改めて記事にまとめていると、もっと調整の余地があると感じた点も多く、わかりやすい記述方法で実装を進めていけたらと思いました。
現在使われている実装方法は、デザインやレイアウトの変更によって使えなくなることもあります。レスポンシブ対応もこなしていかなければならなくなると、もっと煩雑化していくと思います。適材適所でFlexboxを用いてレイアウトの崩れにくい実装を進めていきましょう。
この記事を書いた人
クーシーブログ編集部
1999年に設立したweb制作会社。「ラクスル」「SUUMO」「スタディサプリ」など様々なサービスの立ち上げを支援。10,000ページ以上の大規模サイトの制作・運用や、年間約600件以上のプロジェクトに従事。クーシーブログ編集部では、数々のプロジェクトを成功に導いたメンバーが、Web制作・Webサービスに関するノウハウやハウツーを発信中。
お問い合わせはこちらから
Web制作デザイン、丸ごとお任せ
お問い合わせする
佐々木