「display: inline-block;」でブロック要素を横並びにできますが、それよりも簡単に横並びにできるFlexbox。
この記事では、Flexboxの基本的な使い方とよく使われているプロパティや定番レイアウトの実装方法について解説していきます。
この記事でわかることは以下の通りです。
- Flexboxとは?
- 良く使われるプロパティ
- 定番レイアウトの実例
Flexboxとは?
Flexboxは、横並びレイアウトに使える便利な新機能です。
正式名称は「Flexible Box Layout Module」で、今までよりも簡単にフレキシブル(柔軟性のある)なレイアウトが作成できる!というわけです。
以前よく使われていた「float」は仕組みを理解するのが難しく、初心者がよくつまずく原因となっていました。
また、inline-blockでも横並びに変えられますが、Flexboxはinline-blockより柔軟に並び方を変えられる便利な機能になっています。
Flexboxの基本
Flexboxは、HTML内に親要素となるコンテナを作成し、その中に子要素となるアイテムを作ります。
さっそく、HTML、CSSのコードを見ていきます。
<body>
  <div class="flex-container">
    <div class="flex-item">子要素1</div>
    <div class="flex-item">子要素2</div>
    <div class="flex-item">子要素3</div>
  </div>
</body>/* 親要素(コンテナ) */
.flex-container {
  display: flex;
}
/* 子要素(アイテム) */
.flex-item {
  background-color: skyblue;
  margin: 10px;
}
display: flex;を付けていない状態

display: flex;を付けた状態
親要素コンテナに対して、display: flex;の1行を入れるだけで横並びになりました。
このように、CSS に1行追加するだけで簡単に要素の並び順を変更できます。
良く使われるプロパティ
ここからは、Flexboxで良く使われるプロパティを紹介していきます。
このプロパティは、全て親要素のコンテナに追加します。
flex-wrapで折り返し指定する
Flexboxは、デフォルトのままだと子要素のアイテムを1行で表示できるように幅が自動調整されるようになっています。
flex-wrapを指定することで、折り返して表示することが可能となります。
flex-wrapの値
| 値 | 説明 | 
| nowrap(初期値) | 子要素アイテムを折り返しせず、1行に配置 | 
| wrap | 子要素アイテムを折り返し、複数行に上から下へ配置 | 
| wrap-reverse | 子要素アイテムを折り返し、複数行に下から上へ配置 | 
さっそく、コードをみていきます。
<body>
  <div class="flex-container">
    <div class="flex-item">子要素1</div>
    <div class="flex-item">子要素2</div>
    <div class="flex-item">子要素3</div>
    <div class="flex-item">子要素4</div>
    <div class="flex-item">子要素5</div>
    <div class="flex-item">子要素6</div>
    <div class="flex-item">子要素7</div>
    <div class="flex-item">子要素8</div>
    <div class="flex-item">子要素9</div>
    <div class="flex-item">子要素10</div>
    <div class="flex-item">子要素11</div>
    <div class="flex-item">子要素12</div>
  </div>
</body>.flex-container {
  display: flex;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}
flex-wrapは初期値はnowrapになっているため、このように1行で表示されます。
1行で表示しようとして、子要素アイテムの横幅が自動調整されて横幅が小さくなり、縦に長くなってしまっています。
flex-wrap: wrap;を指定することで、子要素のアイテムが折り返して下に並ぶようになります。
.flex-container {
  display: flex;
  flex-wrap: wrap;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}
flex-directionで並び順を指定する
flex-directionは、子要素アイテムを配置する順番を指定するプロパティです。
flex-directionの値
| 値 | 説明 | 
| row(初期値) | 子要素アイテムを左から右へ配置 | 
| row-reverse | 子要素アイテムを右から左へ配置 | 
| column | 子要素アイテムを上から下へ配置 | 
| column-reverse | 子要素アイテムを下から上へ配置 | 
flex-directionの初期値は、rowで子要素アイテムを左から右へ配置するため、display: flex;を指定するだけで横並びになります。
(flex-directionを指定しなくても横並びになる)
今回は試しに、flex-direction: row-reverse;を指定してみます。
.flex-container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row-reverse;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}
このように、子要素アイテムが右からの順番に並び変わりました。
justify-contentで水平方向の位置を指定する
justify-contentは、子要素アイテムの水平方向の位置を指定するプロパティです。
justify-contentの値
| 値 | 説明 | 
| flex-start(初期値) | 子要素アイテムを左揃えで配置 | 
| flex-end | 子要素アイテムを右揃えで配置 | 
| center | 子要素アイテムを中央揃えで配置 | 
| space-between | 最初と最後の子要素アイテムを両端に配置し、残りの要素は均等に間隔をあけて配置 | 
| space-around | 両端の子要素アイテムも含め、均等に間隔をあけて配置 | 
<body>
  <div class="flex-container">
    <div class="flex-item">子要素1</div>
    <div class="flex-item">子要素2</div>
    <div class="flex-item">子要素3</div>
  </div>
</body>.flex-container {
  display: flex;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}justify-contentの初期値はflex-startなので、何も指定してないと以下の図のように左揃えになります。

justify-content: flex-end;を入れると、右揃えになります。
.flex-container {
  display: flex;
  justify-content: flex-end;
}
justify-content: center;を入れると、中央揃えになります。
.flex-container {
  display: flex;
  justify-content: center;
}
align-itemsで垂直方向の位置を指定する
align-itemsは、子要素アイテムの垂直方向の位置を指定するプロパティです。
align-itemsの値
| 値 | 説明 | 
| stretch(初期値) | 子要素アイテムを上下の余白を埋めるように配置 | 
| flex-start | 子要素アイテムを上揃えで配置 | 
| flex-end | 子要素アイテムを下揃えで配置 | 
| center | 子要素アイテムを上下中央揃えで配置 | 
| baseline | 子要素アイテムをベースラインに合わせて配置 | 
<body>
  <div class="flex-container">
    <div class="flex-item item1">子要素1</div>
    <div class="flex-item item2">子要素2</div>
    <div class="flex-item item3">子要素3</div>
  </div>
</body>.flex-container {
  display: flex;
  height: 100px;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}align-itemsの初期値はstretchのため、何も指定してないと親要素コンテナに合わせて伸び縮みします。
親要素のコンテナにheight: 100px;を指定すると、以下の図のように子要素アイテムも高さ100pxになります。

次に、align-itemsをflex-startにしてみます。
.flex-container {
  display: flex;
  height: 100px;
  align-items: flex-start;
}
.flex-item {
  background-color: skyblue;
  margin: 10px;
}
.item1 {
  height: 50px;
}
.item2 {
  height: 25px;
}
.item3 {
  height: 75px;
}分かりやすくなるように、子要素のアイテムに高さを指定してます。
各アイテムが上揃えで配置されているのが分かると思います。

align-itemsをflex-endにしてみます。
.flex-container {
  display: flex;
  height: 100px;
  align-items: flex-end;
}
各アイテムが下揃えで配置されているのが分かると思います。
良くあるレイアウトの実例
ここからは、Flexboxを利用した良くあるレイアウトの実例を紹介していきます。
2段組みレイアウト
まずは、最もよく見かける2段組みレイアウトの実例です。
<body>
  <div class="flex-container">
    <div class="flex-item">子要素1</div>
    <div class="flex-item">子要素2</div>
    <div class="flex-item">子要素3</div>
    <div class="flex-item">子要素4</div>
    <div class="flex-item">子要素5</div>
    <div class="flex-item">子要素6</div>
  </div>
</body>.flex-container {
  display: flex;
  flex-wrap: wrap;
}
.flex-item {
  background-color: skyblue;
  text-align: center;
  width: 50%;
}上記コードでは以下の画像のようになります。

1つのアイテム幅をwidth: 50%;で半分にし、flex-wrap: wrap;を指定して折り返しにします。
こうすることで、横2列になり、2段組みレイアウトができます。
このままではアイテム同士がくっついて見づらいので、borderを入れてみます。
.flex-container {
  display: flex;
  flex-wrap: wrap;
}
.flex-item {
  background-color: skyblue;
  text-align: center;
  width: 50%;
  border: 1px solid black;
}
2段組みレイアウトが崩れて、縦並びの表示になってしまいました。
これは、borderの2px(左右1pxずつ)分がwidth: 50%;の中に含まれていないためです。
1つのアイテム幅は 50% + 2px(左右1pxずつ)となり、2px分だけ横幅が増えています。そのため、2つ目のアイテムが横に入りきらずに下に並んでしまっています。
これを修正するために、「全ての要素に対して、box-sizing: border-box;」を入れてあげます。
* {
  box-sizing: border-box;
}
.flex-container {
  display: flex;
  flex-wrap: wrap;
}
.flex-item {
  background-color: skyblue;
  text-align: center;
  width: 50%;
  border: 1px solid black;
}上記CSSでは、以下のようにきちんと2段組みレイアウトになります。

box-sizing: border-box;を入れたことで、borderの2px(左右1pxずつ)分が横幅50%の中に含まれるようになったため、2段組レイアウトに戻りました。
box-sizingプロパティに関しては、別の記事にまとめます。
borderと同様にpadding指定を追加する場合も、横幅50%の中に含まれるように、box-sizing: border-box;を指定する必要があります。
margin指定を追加する場合は、少しややこしいです。
marginは「box-sizing: border-box;」を指定しても、横幅50%の中にmargin分は含まれません。
そのため、width自体を縮める必要があります。
* {
  box-sizing: border-box;
}
.flex-container {
  display: flex;
  flex-wrap: wrap;
}
.flex-item {
  background-color: skyblue;
  text-align: center;
  width: calc((100% - 40px) / 2);
  border: 1px solid black;
  margin: 10px;
}「margin: 10px;」を指定すると左右合わせて20px分、1つのアイテム幅が増えます。
2段組みレイアウトにしたいので、2つのアイテムで20px + 20pxで合計40px増えます。
この40pxを考慮したwidthを指定する必要があります。
上記コードのように、calcで100%からまず40pxを引いた値から、2で割って半分にしてあげます。
こうすることで、アイテム幅はmarginを含めた幅になり、以下の図のようになります。

ヘッダー
ヘッダーもFlexboxで作成してみます。
よく見かける左側に企業ロゴ、右側にナビゲーションアイテムが並んでいるヘッダーです。
<body>
  <header>
    <img class="logo" src="image/logo.jpg" alt="">
    <nav>
      <ul>
        <li>
          <a class="nav-link" href="#">Home</a>
        </li>
        <li>
          <a class="nav-link" href="#">Service</a>
        </li>
        <li>
          <a class="nav-link" href="#">About</a>
        </li>
      </ul>
    </nav>
  </header>
</body>header {
  display: flex;                 /* 横並びにする */
  justify-content: space-between; /* ロゴとナビアイテムの間隔をあける */
  align-items: center;           /* ナビアイテムを垂直方向に中央寄せ */
  background-color: skyblue;   /* 背景色 */
}
.logo {
  width: 100px;
}
ul {
  display: flex;                  /* ナビアイテムを横並びにする */
  list-style-type: none;
}
.nav-link {
  color: black;
  margin: 0 10px;
}上記コードでは、以下の図のようになります。

親要素コンテナheaderタグにdisplay: flex;を指定して横並びにしています。
また、ナビゲーションアイテム部分も横並びにしたいので、ulタグにdisplay: flex; を入れています。
ヘッダー、メインコンテンツ、サイドバー、フッターのレイアウト
よく見かけるヘッダー、メインコンテンツ、サイドバー、フッターのレイアウトもFlxeboxを使用して作成してみます。
<body>
  <header>header</header>
  <div class="container">
    <div class="main">main</div>
    <div class="side">side</div>
  </div>
  <footer>footer</footer>
</body>header {
  background: skyblue;
  height: 30px;
}
.container {
  display: flex;
  height: 60px;
}
.main {
  background: pink;
  width: 70%;
}
.side {
  background: orange;
  width: 30%;
}
footer {
  background: lightgreen;
  height: 30px;
}親要素コンテナに display: flex;をして、メインコンテンツとサイドバーを横並びにしています。

まとめ
最後にまとめておきます。
- Flexboxは簡単に並び順を変えることができる
- flex-wrapで折り返し指定する
- flex-directionで並び順を指定する
- justify-contentで水平方向の位置を指定する
- align-itemsで垂直方向の位置を指定する
- 2段組みレイアウトでは、box-sizing: border-box;やcalcを使用する場合がある
