Flexbox のプロパティまとめ

## Flexbox とは？
Flexbox とは、要素を行方向または列方向の1次元にレイアウトするための方法です。
1次元というのは、どちらか1方向しか扱うことができないという意味です。
行と列の2次元でレイアウトを組む場合は、CSS Grid Layout を使う必要があります。

## Flexbox の基礎
Flexbox は「コンテナ」と呼ばれる親要素と、「アイテム」と呼ばれる子要素で構成されています。
```html
<div class="container">
	<div>1</div>
	<div>2</div>
	<div>3</div>
	<div>4</div>
</div>
```
```css
.container {
	display: flex;
}
```

## コンテナに指定するCSSプロパティ
まず、コンテナに指定する CSS プロパティです。

### display プロパティ
要素に display: flex; または display: inline-flex; を指定することで、その要素がコンテナになります。
display: flex を指定すると、コンテナ要素がブロック要素のようになります。
display: inline-flex を指定すると、コンテナ要素はインラインブロック要素のようになります。
display: flex や inline-flex が指定された子要素は、自動的にアイテムになります。

```html
<div class="container">
	<div>1</div>
	<div>2</div>
	<div>3</div>
	<div>4</div>
</div>
```

```css
.container {
	display: flex;
}
```
![02_display.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/91e234ad-daf5-a295-2d0a-04a449f594f1.png)
※ 点線で囲まれているのがコンテナです。

### flex-direction プロパティ
アイテムの並ぶ向きを指定します。
- row（デフォルト）：アイテムは横並びになります。
- column：アイテムは縦並びになります。
- それぞれに "reverse" を付けると、並び順が逆になります。
```css
.container {
	display: flex;
	flex-direction: row;
}
```
![03_flex-direction.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/91bd782e-f9eb-f078-3a97-c95613c1211c.png)

### justify-content プロパティ
flex-direction プロパティで決めた方向に沿って、アイテムの配置方法を指定します。
- flex-start：始点
- flex-end：終点
- center：中央揃え
- space-between：最初と最後のアイテムを両端に配置し、残りのアイテムを等間隔に配置
- space-around：最初と最後のアイテムを半分だけ間隔を空け、残りのアイテムを等間隔に配置
- space-evenly：全てのアイテムを等間隔に配置

```css
.container {
	display: flex;
	justify-content: flex-start;
}
```
![04_justify-content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/5778d8f5-0723-c83b-8ecb-42510c2e1e0a.png)

### align-items プロパティ
flex-direction プロパティで決めた方向とは逆のアイテムの配置方法を指定します。
つまり、flex-direction: row を指定している場合、垂直方向の配置方法です。
- flex-start：始点（上揃え）
- flex-end：終点（下揃え）
- center：中央揃え
- baseline：ベースラインで揃える
```css
.container {
	display: flex;
	align-items: flex-start;
}
```
![05_align-items.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/e12db09d-09e2-a6ad-da0e-4d274b40b463.png)

## アイテムに指定する CSS プロパティ
次に、アイテムに指定する CSS プロパティです。
以下の例では、背景色が異なる3番目の要素に各プロパティを設定します。

order プロパティ
アイテムの並び順を指定します。
・0（デフォルト）：HTML に記述された順番に並びます。
・正の数：値の昇順に並びます。
・負の数：値の降順に並びます。

```html
<div class="container">
	<div>1</div>
	<div>2</div>
	<div class="item-3">3</div>
	<div>4</div>
</div>
```

```css
.container {
	display: flex;
}
.item-3 {
	order: 1;
}
```
![06_order.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/165af18e-58bf-0160-53e9-4862088f7489.png)

### align-self プロパティ
コンテナで指定した align-items プロパティを上書きします。
各プロパティの意味は align-items と同じです。
- flex-start：始点（上揃え）
- flex-end：終点（下揃え）
- center：中央揃え
- baseline：ベースラインで揃える

```css
.container {
	display: flex;
}
.item-3 {
	align-self: flex-start;
}
```
![07_align-self.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/c2174b17-a384-0e20-0d31-93247b60b1db.png)

### flex-basis プロパティ
アイテムの初期サイズを定義します。
デフォルトは auto で、コンテンツの幅によって決まります。
コンテナの幅によって、実際に表示される幅は指定したサイズより小さくなる場合があります。
```css
.container {
	display: flex;
}
.item-3 {
	flex-basis: 30%;
}
```
![08_flex-basis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/c23e53d1-b0e2-2862-9d16-273f509006c7.png)


### flex-grow プロパティ
コンテナの領域が余った場合、子要素の伸び具合を指定します。
- 0（デフォルト）：伸ばさない
- 正の数：値の比率に応じて伸ばす
マイナスは指定できません。
```css
.container {
	display: flex;
}
.item-3 {
	flex-grow: 1;
}
```
![09_flex-grow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/f0ddeb8e-ef26-745c-37de-5a62e3543c4c.png)


### flex-shrink プロパティ
flex-grow とは逆にコンテナの領域が足りない場合、子要素の縮み具合を指定します。
デフォルトは 1 で、各アイテムに指定されたプロパティの比率によって縮みます。
```css
.container {
	display: flex;
}
.item-3 {
    flex-basis: 30%;
	flex-shrink: 0;
}
```
![10_flex-shrink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/a9f2c2f5-d97a-9410-4bd5-ba0ec721e53d.png)
flex-shrink: 1 を指定した場合、3番目の要素がコンテナの幅に合わせて縮んでいます。

### flex-basis、flex-grow、flex-shrink のショートハンド
上記の 3 プロパティは flex プロパティでまとめて指定できます。
指定する順序は flex-grow, flex-shrink, flex-basis の順です。
各プロパティのデフォルト値を表すと "flex: 0 1 auto;" となります。

## 実例
最後に、これまで紹介したプロパティを使ってありがちな 3 カラムレイアウトを実装してみます。

```html
<body>
	<header>Header</header>
	<div class="wrapper">
		<main>Main</main>
		<nav>Nav</nav>
		<aside>Side</aside>
	</div>
	<footer>Footer</footer>
</body>
```
```css
body {
	display: flex;
	flex-direction: column;
	height: 100vh;
	margin: 0;
}
header,
footer {
	flex-grow: 0;
	padding: 1rem;
	background-color: #eee;
	border-top: 1px solid #bbb;
	border-bottom: 1px solid #bbb;
}
.wrapper {
	flex-grow: 1;
	display: flex;
	flex-direction: row;
}
main {
	flex-grow: 1;
	padding: 1rem;
}
nav {
	flex-grow: 0;
	order: -1;
	width: 200px;
	padding: 1rem;
	border-right: 1px solid #bbb;
	background-color: #cde;
}
aside {
	flex-grow: 0;
	width: 200px;
	padding: 1rem;
	border-left: 1px solid #bbb;
	background-color: #cde;
}
```
![11_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129344/042bab41-6050-6e97-052b-e68118e3ab97.png)

やっていることは以下の通りです。
- body を flex-direction: column; にして縦並びにします。
- header と footer は flex-grow: 0; にして幅が伸びないようにしています。
- wrapper はアイテムでもありコンテナでもあります。
アイテムとして flex-grow: 1 にして余った高さを伸ばしています。
また、flex-direction: row; にして横並び 3 カラムのコンテナとしています。
- nav と aside は width を指定した上で flex-grow: 0; にして幅が伸びないようにしています。
nav は 3 カラムの一番左に表示するため order: -1; にしています。
- main は flex-grow: 1; にして 3 カラムの余った幅を伸ばしています。

## 参考
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Flexible_Box_Layout