CSSレイアウト

# フレックスボックス
フレックスボックス（Flexbox）は、
要素を横や縦にきれいに並べたいときに使うレイアウト方法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/c9bf7ab2-a047-41e8-84ed-6f99ec3364e1.png)

## フレックスコンテナ・アイテムとは
- CSSで`display: flex;`を指定された親要素 のこと（子要素を柔軟に配置できる箱のこと）です。
- 親要素に指定すると、その中の子要素（フレックスアイテム）が、自動的に柔軟に配置できるようになります。
- フレックスコンテナには、主軸・交差軸という軸が設定されます。
    - フレックスコンテナの子要素は、**主軸の流れによって並べられる**こととなります。
- フレックスコンテナは**ブロック要素**となります。
    - `display: inline-flex;`とすると、横に並ぶフレックスコンテナとして設定できます。
- フレックスアイテムは、ブロック要素でもインライン要素でもありません。フレックスアイテムは、仕様によって定義された独自の挙動を持ちます。
- フレックスアイテムの要素としての認識は、コンテンツ、`padding`、`border`、`margin`を含めた、その要素が占める「ボックス全体」 となります。

:::note info
- フレックスアイテムは、`width`や`max-width`などで明示的に幅が指定されていない場合、**コンテンツの幅に合わせて**縮もうとします。
- さらに、親のフレックスコンテナの幅よりもフレックスアイテムの合計幅が大きくなるような場合（例えば、たくさん子要素が並んだり、子要素のコンテンツが長くなったりした場合）でも、フレックスアイテムは縮んで親の幅に収まろうとします。これが `flex-shrink: 1`の役割です。
:::

## 基本の使い方
- **親要素**に`display: flex;`を指定する
- **子要素**は、デフォルトで`flex-direction: row;`（横並び）になる
    - 子要素はブロック要素でも横並びに変更される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/4782cf25-9c9c-49db-b5c9-a1caf3ef805e.png)
フレックスコンテナ・アイテムには、上記のようにそれぞれ設定できるプロパティが複数あります。
今回はよく使用する8つを見ていきます。

## フレックスコンテナのプロパティ
### 1.`flex-direction`
**主軸の方向**を決めるためのプロパティです。
前述の通り、デフォルトは`flex-direction: row;`（横並び）となります。
#### `flex-direction: row`
- 左から右へ主軸が設定されます。
![スクリーンショット 2025-05-08 10.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/7c2ade07-019d-4e9b-b340-490bbf19369a.png)
- 左右幅：子要素のコンテンツに合わせて（`padding`なども含めて）必要な幅になる。
- 高さ：デフォルトでは、子要素のコンテンツに合わせて必要な高さになる。親要素に明示的な高さが指定されている場合は、その制約を受けることもある。

#### `flex-direction: row-reverse`
- 主軸の方向を右から左へすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/293c1149-a368-46de-bfb0-33f1a4968b05.png)

#### `flex-direction: column;`
- 主軸の方向を縦並びに変更することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/4dc2477e-ca6f-484b-94cd-3957fcdd757f.png)

- 左右幅：親要素の幅いっぱいに広がる。（`Flexbox` の `column` レイアウトにおけるデフォルトの挙動。）
- 高さ：子要素のコンテンツに合わせて必要な高さになる。

#### `flex-direction: column-reverse;`
- 主軸を下から上へ、要素を縦並びにすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/f0fa78bc-3c02-403e-99fa-2d36b336c3bf.png)



### 2.`justify-content`
**主軸方向**で要素をどう揃えるかを制御するためのものです。

#### `justify-content: flex-start`
主軸の開始地点に要素を揃えるという意味です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/a16ac992-ff87-4104-b1e2-b0eb3e70aa0f.png)

#### `justify-content: center`
主軸に対して中央に揃えることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/ab7f9012-6424-4ed2-89d7-9a4f460a1330.png)

#### `justify-content: flex-end`
主軸に対して、終了地点に揃えるという意味です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/4c0ea863-d7aa-49e7-9475-ba491cb47cca.png)

#### `justify-content: space-between`
要素間の間隔が均等に配置される揃いかたになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/547f6a1d-dd8d-4a92-974b-7323b1caaf52.png)

### 3.`align-items`
2の`justify-content`は主軸方向での揃えを指定できるものでしたが、`align-items`は交差軸方向での揃えになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/4f169106-f617-45de-ba94-445e9a1ff2b7.png)

:::note info
交差軸方向に余白がないといけないので、この例だとフレックスコンテナに十分な高さがある場合にだけ使えるプロパティになります。
:::

#### `align-items: flex-start;`
交差軸の開始地点に要素を揃えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/995dbaac-09f7-4f5f-a0b2-d2f1ef923024.png)

#### `align-items: flex-end;`
交差軸の終了地点に要素を揃えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/5bfab0a4-6179-4de2-8571-9710e36feda1.png)

#### `align-items: center;`
交差軸に対して中央に揃えるという意味になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/b8f7aa39-18cd-4de1-ae5a-00b2c32bc9a6.png)

:::note info
`align-items: center;`と
`justify-content: center;`を組み合わせることで、
フレックスコンテナに対して要素を**上下左右中央揃えにする時**によく使われたりします。
:::

:::note info
- フレックスアイテムの要素としての認識は、コンテンツ、`padding`、`border`、`margin`を含めた、その要素が占める「ボックス全体」 となります。
- そのため、たとえばフレックスアイテムに背景色を設定して中央揃えにすると、その背景色も、コンテンツ、`padding`と共に、その要素のボックス全体として移動し、中央揃えとなります。
:::

### 4.`flex-wrap: wrap`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/fa4c4d2c-6dbd-4d7c-b319-b741d4deaace.png)
上記のように、フレックスアイテムの幅の合計が、コンテナの幅を超えた場合に使えるプロパティになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/e6a965ec-0c12-4a7a-81b2-44864f80ac78.png)
デフォルトでは、上記のようにコンテナに収まるようにこのように縮もうとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/817f45c7-cb38-4045-b937-cf16fc1b9ee4.png)
しかし、`flex-wrap: wrap`を設定すれば溢れた分を折り返しすることができるようになります。

:::note warn
折り返されるとそれぞれの行は`Flex-line`と呼ばれる行で分割されて、
フレックスアイテムに設定したプロパティは行ごとに同じ値が適用されます。
:::

例えば`flex-wrap: wrap`で折り返された状態で、
`justify-content: space-between;`と設定すると、
下記のように行ごとに要素間の間隔が均等に配置される揃いかたになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/2e601df8-396f-429c-9af1-485fba93575b.png)

### 5.`gap`
並んだ要素の間に隙間を作るための設定です。
```css
.親要素 {
  display: flex; /* または display: grid; */
  gap: 20px; /* 例えば、全ての隙間を20pxにする */
}
```
## フレックスアイテムのプロパティ

### 1.`align-self`
`align-items`では子要素すべてに交差軸の配置が設定されますが、
`align-self`では、設定された値のみ交差軸方向の`flex-start`、`flex-end`、`center`の位置に揃えることができます。
- `flex-start`: 交差軸の開始地点に要素を揃える
- `center`: 交差軸に対して中央に要素を揃える
- `flex-end`: 交差軸の終了地点に揃える

####  交差軸方向ではなく主軸方向で個々のフレックスアイテムを揃えたい場合
`margin: auto`を使用します。
フレックスボックスでは、`margin: auto;`を使うと、
その要素のその方向の余白が「**利用可能な空間を自動で最大に広げて埋める**」という特別な能力を持ちます。

- `margin-left: auto;` なら、左側の空きを全部吸い込んで**右へ押し出す**。
- `margin-right: auto;` なら、右側の空きを全部吸い込んで**左へ押し出す**。
- 両方 (`margin: auto;`または `margin-left: auto;` `margin-right: auto;`) なら、左右の空きを均等に吸い込んで**中央に配置する**。

そのため、例えば下記画像の3のみを右寄せにしたい場合、
`margin-left: auto;`とすると実現できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/8aeae1ee-6312-4be4-b63c-2c6670f18625.png)



### 2.`order`
子要素の表示順番を変えることができます。
`order=0`は初期値となり、小さい順に並ぶ形となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/d28f0d38-9dfa-4be1-a581-7dbe65afc88b.png)

```CSS
/* 3つの中で1番右に配置 */
main {
  order: 3;
}

#sub1 {
  order: 1;
}

#sub2 {
  order: 2;
}
```
:::note info
子要素すべてに指定することで、ソースコード順の表示となります。
:::

### 3.`flex`
子要素に`flex`プロパティを設定することで、
親要素の幅に対して子要素の幅をどう変化するか指定できます。

フレックスアイテムの幅の合計がコンテナに満たなかったり、逆にコンテナの幅を超えたときにどうするかを指定できます。

#### `flex: initial`;
- デフォルトです。
- 縮小はされても拡張はされない状態となります。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/13786454-3e68-41ec-b7b9-0fa4be0b3702.png)


#### `flex: auto;`
- 親要素に空きが出ないように子要素の幅を拡張・縮小させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/e4c08a24-b6a7-4512-a9b6-373d8cb00bc2.png)

#### `flex:none`
- 子要素の幅は固定され、拡張・縮小はされません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627033/1c82653f-3631-48a9-b305-54001b93c889.png)


#### 実数を設定する
- `flex`に指定した実数の割合で幅が調整されます。
- `auto`と同じく拡張・縮小されます。

##### よく使われる`flex: 1;`
- `flex: 1;`は、空いているスペースを、他の`flex: 1;`の仲間たちと公平に分け合って利用します。
- つまり、全てのフレックスアイテムを同じ幅にしたい（等幅）時に、よく使用されます。

```HTML
<section>
<!-- フレックスアイテム1 -->
  <div>
    <h2>すごい家具</h2>
    <p>
      すごい家具です。
    </p>
  </div>
<!-- フレックスアイテム2 -->
  <div>
    <img src="product-1.png" width="400" height="400" alt="すごい家具" />
  </div>
</section>
```
- 上記のようなHTMLがあるとします。
    - `section`が親要素としてフレックスアイテムの`div`要素が2つ存在します。
- 下記のCSS設定のようにフレックスアイテムに`flex:1;`を設定することで、ふたつの`div`要素（フレックスアイテム）を等幅に設定することができます。
```CSS
.product div {
  flex: 1; 
}
```

# グリットレイアウト
Webページを行と列に分けて、要素を配置するためのレイアウトシステム💪🏻

## 基本的な考え方
- グリッドコンテナ（親要素）を定義する
- グリッドアイテム（子要素）をその中に配置する
- 行や列のサイズを設定して、アイテムを自由に配置する

## 意外な落とし穴
- グリッドの対象になるのは、グリッドを指定している直下の要素だけ！
``` HTML
<main>
  <article> ... </article>   ← これが1個目の子
  <div id="sub">              ← これが2個目の子
    <article> ... </article>
    <article> ... </article>
  </div>
</main>
```
上記のコードで`main`にグリッドを指定しているとすると、
グリッド上で配置されてるのは「`article`」と「`#sub`」だけ！

 **そのため、表示は下記のようになる！**
```
| article（mainの子）| article（subの中） |
|                   | article（subの中） |

```
`#sub`自体は グリッドじゃないから、
通常のブロック要素として中身は縦に積まれるんだよね。

## グリッドシステムの使い方
### 1.列を指定する
 `grid-template-columns` は「列（カラム）の幅や数」を決める

```CSS
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
```
この指定は、
- 横に3つ並べられるスペースを用意する。
- アイテム（子要素）が3つ以下なら1行で収まる。
- 4つ以上になったら、次の行が自動的に作られる！

☁️表示イメージ：
```
アイテム1 アイテム2 アイテム3  
アイテム4 アイテム5 アイテム6
```

:::note info
`fr`について
- 指定した数値の比率で縦・横に分配する
- `grid-template-columns: 1fr 2fr 3fr;`とすると、縦列の幅は「1:2:3」となる
- 値の中に「fr」つきでない値が含まれている場合は、先に「fr」つきでない幅が確保され、残った幅を「fr」で指定された数値の比率で分配する
:::


### 2.列と行を指定する
 `grid-template-rows` で「行」を指定
```CSS
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 100px;
}
```
この指定は、
- 「横3つ」「縦2つ」のグリッドを作る

### 3.行と列の指定方法
```CSS
grid-column: 1/2;
grid-row: 2;
```
この指定だと、
- 横方向のグリッドの「1列目の線から2列目の線まで」の領域に置く（つまり「1列目のセルに配置」）
- 縦方向のグリッドの「2行目」に置く

例：★の位置だよ！
```
 --- --- ---
|   |   |   |
 --- --- ---
| ★ | 　 |  |
 --- --- ---
```


---

未来の自分のために、誰かのためにこの記事が役に立てば幸いです✨🧚🏻