【2022年12月版】Flexboxチートシート

# 前置き
metaps Advent Calendar 2022 の14日目です。
レスポンシブデザインの肝とも言えるFlexboxについてご紹介します。

今までにいくつもの紹介記事やチートシートがある中でなぜ今あえて紹介するのかというと、今年6月にIE11のサポート終了になったことでIE11で対応できていなかったCSSプロパティが使えるようになり、自分の中で今使えるものをまとめておこうと思ったからです。


# Flexboxの基本

```html:HTMLのサンプル
<ul class="flexBase">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
```
こんな感じでサンプルをflexboxで扱いたい場合、親要素側のCSSに`display: flex;`を指定すると、子要素が横並びに並びます。



この時、`display: inline-flex;`を使うと親要素がinline要素になるため、親要素同士を並べることができます。


# フレックスコンテナ - 親要素に指定するプロパティ -
## flex-direction - flexboxの並べる方向 -
![flex-direction.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31662/6e85b8d8-36a0-0518-684e-ba1ea06c4e64.png)

ここからは実際のスタイリングの部分です。

`flex-direction`はflexboxの子要素の並べる方向を決めるプロパティです。LPなどのレイアウトや、レスポンシブデザインでよく使います。

- `flex-direction: row;` **[初期値]** 　横に左から右に向かって並べる
- `flex-direction: row-reverse;`　横に右から左に向かって並べる
- `flex-direction: column;` 　縦に上から下に並べる
- `flex-direction: column-reverse;` 　縦に下から上に並べる


```scss:flex-direction: row;
.flexBase {
  display: flex;
  flex-direction: row;
}
```

```scss:flex-direction: row-reverse;
.flexBase {
  display: flex;
  flex-direction: row-reverse;
}
```

```scss:flex-direction: column;
.flexBase {
  display: flex;
  flex-direction: column;
}
```

```scss:flex-direction: column-reverse;
.flexBase {
  display: flex;
  flex-direction: column-reverse;
}
```


## flex-wrap - 折り返しの有無 -
![flex-wrap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31662/89b9ccf8-05ea-05e0-0ddb-b5a7841b5b03.png)

`flex-wrap`はflexboxの子要素を親要素内に1行で並べるか、親要素に合わせて折り返すかを指定するプロパティです。

- `flex-wrap: nowrap;` **[初期値]**　折り返さず１行に並べる
- `flex-wrap: wrap;`　　折り返して並べる。折り返しは上から下になる。
- `flex-wrap: wrap-reverse;`　折り返して並べる。折り返しは下から上になる。



```scss:flex-wrap: nowrap; 
.flexBase {
  display: flex;
  flex-wrap: nowrap;
}
```

```scss:flex-wrap: wrap; 
.flexBase {
  display: flex;
  flex-wrap: wrap;
}
```

```scss:flex-wrap: wrap-reverse; 
.flexBase {
  display: flex;
  flex-wrap: wrap-reverse;
}
```

## flex-flow - flex-direction、flex-wrapの一括指定 -
`flex-direction`や`flex-wrap`を両方指定する時はまとめて指定する方法もあります。
`flex-flow`は、この二つのプロパティを一括で指定できるプロパティです。

- `flex-flow: row nowrap;`**[初期値]**

## justify-content -水平方向の配置-
![justify-content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31662/0c340f60-2aeb-066d-86f8-6031aae511f7.png)

`justify-content`は、flexboxの子要素を水平方向にどのように配置するかを指定するプロパティです。
このプロパティを使うことで子要素間の間隔を細かく調整せずに並べたりすることができます。
ここでは、わかりやすくするために`flex-direction: row;`の時の配置を書いています。


- `justify-content: flex-start;` **[初期値]**　
子要素を親要素の左端に寄せて配置する
- `justify-content: flex-end;`　
子要素を親要素の右端に寄せて配置する
- `justify-content: center;`　
子要素を親要素の中央に配置する
- `justify-content: space-between;`
最初と最後の子要素は端に寄せ、残りの子要素を等間隔に配置する
- `justify-content: space-around;`
最初と最後の子要素は半分だけ間隔を置いてから、残りは等間隔に配置する
- `justify-content: space-evenly;`
全ての子要素の間隔を等間隔に配置する
- `justify-content: stretch;`
全ての子要素の間隔を等間隔に配置し、サイズが`auto`の子要素は親要素に合わせて引き伸ばされる


```scss:justify-content: flex-start; 
.flexBase {
  display: flex;
  justify-content: flex-start;
}
```
```scss:justify-content: flex-end;
.flexBase {
  display: flex;
  justify-content: flex-end;
}
```
```scss:justify-content: center;
.flexBase {
  display: flex;
  justify-content: center;
}
```
```scss:justify-content: space-between;
.flexBase {
  display: flex;
  justify-content: space-between;
}
```
```scss:justify-content: space-around;
.flexBase {
  display: flex;
  justify-content: space-around;
}
```
```scss:justify-content: space-evenly;
.parent {
  display: flex;
  justify-content: space-evenly;
}
```
```scss:justify-content: stretch;
.flexBase {
  display: flex;
  justify-content: stretch;
}
```

## align-items - 垂直方向の配置 -
![align-items.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31662/83018a29-0ab7-1cee-bb6c-c2833100961d.png)


`align-items`は、flexboxの子要素を垂直方向にどのように配置するかを指定するプロパティです。
ここでもわかりやすくするために、`flex-direction: row;`の時の配置を書いています。

- `align-items: stretch;` **[初期値]**　
子要素を親要素の高さいっぱいに広げて配置する
- `align-items: flex-start;`
子要素を親要素の上側に寄せて配置する
- `align-items: flex-end;`
子要素を親要素の下側に寄せて配置する
- `align-items: center;`
子要素を親要素の中央に配置する
- `align-items: baseline;`
子要素のベースラインに沿って配置する
※ベースラインというのは、英字等のテキストの基準となる線のことなので和文ではあまり関係がありません。




```scss:align-items: stretch;
.flexBase {
  display: flex;
  align-items: stretch;
}
```
```scss:align-items: flex-start; 
.flexBase {
  display: flex;
  align-items: flex-start;
}
```
```scss:align-items: flex-end;
.flexBase {
  display: flex;
  align-items: flex-end;
}
```
```scss:align-items: center;
.flexBase {
  display: flex;
  align-items: center;
}
```
```scss:align-items: baseline;
.flexBase {
  display: flex;
  align-items: baseline;
}
```

## align-content - 折返しがある場合の垂直方向の配置 -
![align-content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31662/f14cf531-61b1-08e5-bc20-787d0c900e13.png)

先の`align-items`プロパティは、折り返しがある場合には有効になりません。
折り返しのある複数行の子要素を垂直方向に配置するには`align-content`プロパティを使用します。

- `align-content: stretch;` **[初期値]**　
子要素を親要素の高さいっぱいに広げて配置する
- `align-content: flex-start;`
子要素を親要素の上側に寄せて配置する
- `align-content: flex-end;`
子要素を親要素の下側に寄せて配置する
- `align-content: center;`
子要素を親要素の中央に配置する
- `align-content: space-between;`
最初と最後の子要素は端に寄せ、残りの子要素を等間隔に配置する
- `align-content: space-around;`
最初と最後の子要素は半分だけ間隔を置いてから、残りは等間隔に配置する
- `align-content: space-evenly;`
全ての子要素の間隔を等間隔に配置する




```scss:align-content: stretch;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: stretch;
}
```
```scss:align-content: flex-start; 
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
}
```
```scss:align-content: flex-end;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-end;
}
```
```scss:align-content: center;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: center;
}
```
```scss:align-content: space-between;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}
```
```scss:align-content: space-around;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: space-around;
}
```
```scss:align-content: space-evenly;
.flexBase {
  display: flex;
  flex-wrap: wrap;
  align-content: space-evenly;
}
```

## column-gap - 水平方向の間隔の指定 -
ここまで紹介してきたプロパティは、親要素に指定すると親要素のサイズに合わせて自動的に間隔が決定するプロパティになります。
レスポンシブデザインでは画面に合わせて間隔が狭まっていくので便利なのですが、
「要素の間隔は固定数値で指定したい」という場合に、利用できるプロパティが`gap`プロパティになります。

`column-gap`プロパティは、水平方向の子要素間の間隔を指定できます。
マイナスの値は指定できません。

```scss:column-gap
.flexBase {
  display: flex;
  column-gap: 40px;
}
```

## row-gap - 垂直方向の間隔の指定 -
`row-gap`プロパティは、垂直方向の子要素間の間隔を指定できます。
マイナスの値は指定できません。

```scss:row-gap
.flexBase {
  display: flex;
  row-gap: 2em;
}
```

## gap - column-gap, row-gapの一括指定 -
水平、垂直方向の間隔を`gap`プロパティで一括で指定することができます。
マイナスの値は指定できません。


# フレックスアイテム - 子要素に指定するプロパティ -
ここからは子要素側に指定するプロパティを紹介します。

## order - 並ぶ順番 -
`order`は並び順を指定することができるプロパティです。
PCサイズとスマホサイズなどで要素を並べる順番が変わる場合に使います。

<p class="codepen" data-height="300" data-slug-hash="WNOPXWE" data-user="amiami" style="height: 300.8046875px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/WNOPXWE">
  flex-box</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## flex-grow - 伸びる比率 -
`flex-grow`は、親要素にサイズが指定されていない余りのスペースがある時に
指定した子要素を他の子要素と比べて、どのくらい伸ばすかを指定するプロパティです。
数字が大きい方が伸びます。マイナスの値は指定できません。

<p class="codepen" data-height="300" data-slug-hash="LYrKpWW" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/LYrKpWW">
  flex-grow</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- `flex-grow: 0;`**[初期値]**　指定された子要素は伸ばさない


## flex-shrink - 縮む比率 -
`flex-shrink`は、親要素に対して子要素が大きく、子要素が収まりきらない時に
指定した子要素を他の子要素と比べて、どのくらい縮ませるかを指定するプロパティです。
数字が大きい方が縮みます。マイナスの値は指定できません。

<p class="codepen" data-height="300" data-slug-hash="VwdJvMM" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/VwdJvMM">
  flex-shrink</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- `flex-shrink: 1;`**[初期値]**　指定された子要素は等倍で縮む
- `flex-shrink: 0;`　指定された子要素は縮まない



## flex-basis - 基準のサイズ -
`flex-basis`は、`flex-grow`と`flex-shrink`で伸縮する前の初期サイズを指定するプロパティです。
子要素に`width`と`flex-basis`の両方が指定されている際は、`flex-basis`が優先されます。

<p class="codepen" data-height="300" data-slug-hash="PoarPBy" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/PoarPBy">
  flex-basis</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- `flex-basis: auto;`**[初期値]**　指定された子要素の初期サイズは`width`に従う


## flex - flex-grow、flex-shrink、flex-basisの一括指定 -
`flex`は、`flex-grow`,`flex-shrink`、`flex-basis`の一括指定プロパティです。

- `flex: 0 1 auto;`**[初期値]**
- `flex: 1;`
単位のない値、1つの場合、`flex-grow`の数値と見做され、`flex-shrink: 1;` `flex-basis: 0;`となる。
- `flex: auto;`
`flex-grow: 1;` `flex-shrink: 1;` `flex-basis: auto;`になる

```scss:flex
li {
  flex: 1 1 300px;
}
```

## align-self - 子要素個別での垂直方向の配置 -
親要素側で`align-items`や`align-content`によって子要素まとめて垂直方向の配置ができます。
配置場所をそれぞれ違う方向に寄せたいときに使うのが、`align-self`プロパティです。

`align-items`、`align-content`と`align-self`が同時に指定されている場合、
`align-self`で指定された値が優先されます。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="ExRBKwJ" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/ExRBKwJ">
  Untitled</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- `align-self: auto;`**[初期値]** 
`align-items`の設定値を引き継ぐ
- `align-self: stretch;`
親要素の高さいっぱいもしくは一番大きな子要素に合わせて配置する
- `align-self: flex-start;`
親要素の上側に寄せて配置する
- `align-self: flex-end;`
親要素の下側に寄せて配置する
- `align-self: center;`
親要素の中央に配置する
- `align-self: baseline;`
ベースラインに沿って配置する

```scss:align-self
li:nth-child(3) {
  align-self: flex-end;
}
```


# よくある使い方
ここまで長々とここのプロパティを紹介してきましたが、実際どのように利用するのかもいくつか紹介したいと思います。


## 要素の天地左右中央配置
一番想像がつきやすいものが、親要素の中心に子要素を配置するものだと思います。


<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="abKgvXW" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/abKgvXW">
  要素を天地中央に寄せる</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss:要素を天地左右の中央に配置
.flexBase {
  display: flex;
  justify-content: center;
  align-items: center;
}
```

`justify-content: center;`で水平方向の中心に寄せ、`align-items:center;`で垂直方向の中心に指定することで、親要素の天地左右中央に配置することができます。簡単ですね。

## 左右互い違いレイアウト
LPなどで、画像と文章のセットを一項目ごとに順番を変えて互い違いになるようなレイアウトがよくあります。
こちらもflexboxを使うことで、HTML側の構造を変えることなく簡単に表現できます。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="KKejdLp" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/KKejdLp">
  左右互い違いレイアウト</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss:左右違い違いレイアウト

li:nth-child(2n) {
  display: flex;
  flex-direction: row-reverse;
}
```

このように、偶数行だけ、`flex-direction: row-reverse;`を指定するだけです。


## レスポンシブで並び順変更
デスクトップサイズでは横に並んでいるメニューが、スマホサイズでは縦になることも多々あります。
こちらもflexboxで簡単に設定できます。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="KKejVPd" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/KKejVPd">
  レスポンシブで並び順変更</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss:レスポンシブで並び順と配置変更
.flexBase {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;

  @media screen and (max-width: 420px) {
    flex-direction: column;
    justify-content: flex-start;
  }
}
```
デスクトップでの閲覧時は、`flex-direction: row;`（初期値）で左から右に、`justify-content: flex-end;`で右端寄せで並んでいます。
画面サイズが一定ラインより狭くなると、`flex-direction: column;`で上から下の順番になります。
`flex-direction: column;`の時は、`align-items`と`justify-content`の示す方向が入れ替わるので、上側に寄せるために`justify-content: flex-start;`を指定し直しています。
（詳しく知りたい方は、MDNのこのあたりをご確認ください。）


https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container#%E4%B8%BB%E8%BB%B8%E3%81%AE%E5%A4%89%E6%9B%B4)


## カード型レイアウト
よくあるカードレイアウトですが、文章量が可変でも、文章の下にあるボタンの位置は簡単に固定できます。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="QWxXyWw" data-user="amiami" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/amiami/pen/QWxXyWw">
  カード型レイアウト</a> by Ami Asano (<a href="https://codepen.io/amiami">@amiami</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```scss:カード型レイアウト
li {
  display: flex;
  flex-direction: column;
}
.buttonArea {
  margin-top: auto;
}
```

本文の長さはカードによってまちまちですが、カード本体を`flex-direction: column;`で上から下に並べ、位置を固定したいボタンに`margin-top: auto;`を指定することで、一番本文が長いカードに合わせてボタンが下に揃うようになります。
このテクニックは、画面下に固定したいfooterにも使うことができます。

## 終わりに
長々とflexboxのプロパティについて記載しました。CSSは、日々新しい仕様が追加されていて、初めて見るプロパティもあるかもしれません。こちらは、2022年12月現在、主要モダンブラウザで利用できるものになります。
使いこなせるととてもマークアップが楽になるので、よければ参考にしてください。



## 補足 `flex-basis: content;`について
`flex-basis: content;`という設定値があり、こちらは、指定された子要素のコンテンツ量に合わせてベースサイズを指定するというものになります。2022年12月現在、safariではTP版しか利用できないので本文中には載せていません。