MUI (Material UI) の Container で最大横幅を設定する ―― ヘッダーの幅固定もできるよ

# MUI (Material UI) の Container コンポーネント

**左右に余白つき・最大値固定・中央揃え** のレイアウトを実現したいとき、Material UI (@mui/material) の Container コンポーネントを使えば、短い記述でこのようなレイアウトを実現することが出来ます。

（下の画像は、分かりやすさのため、背景はグレーで、Container は白くしています。)

| 画面が幅広のとき | 画面が幅狭のとき |
| :-:             |:-:             |
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/7597e5f5-855b-7366-058b-8b4ea0c7e982.png) |![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/64e6cd90-8726-798a-bb74-adc4ff0febf2.png) |

## 公式ドキュメント

### コンポーネント解説

https://mui.com/material-ui/react-container/

### API ドキュメント

https://mui.com/material-ui/api/container/

## 使用した MUI のバージョン

|パッケージ|バージョン|
|-|-|
| @emotion/react  | 11.10.0 |
| @emotion/styled | 11.10.0 |
| @mui/material   | 5.10.2  |


# Container と Paper を組み合わせるときの注意


Container と Paper を組み合わせて padding を設定したい場合、下のように書くことになります。

:::note info
`padding` -> `p`, `marginY` -> `my` と省略可能です。
[System properties についての公式ドキュメント](https://mui.com/system/properties/)
:::

```tsx:✅ContainerとPaperの組み合わせ
<Container>
  <Paper sx={{ padding: 4, marginY: 2 }}>
    ここにコンテンツが入ります。
  </Paper>
</Container>
```

Container は左右に padding を持っていて、子要素の横幅を制限するような実装になっているため、

```tsx:❌paddingが上書きされてしまう
<Container component={Paper} sx={{ padding: 4 }}>
```

 のように設定してしまうと、Container 本来の padding が上書きされてしまいます。 だから Container の子として padding つき Paper を配置しないといけなかったんですね。



# maxWidth &mdash; 最大幅を設定

`maxWidth` に ブレークポイントの値を指定すると、Container はそのブレークポイントを上限として、画面幅に合わせてリキッドに幅が変化するようになります。下図の左側の折れ線グラフで模式的に示しています。

ただし、何も指定していない場合には`"lg"` が設定され、あえて `false` を指定した場合には上限なしにリキッドに幅が変化するようになります。

```tsx
<Container maxWidth="md"> 
<Container>{/* デフォルトで "lg" が指定されている */}
<Container maxWidth={false}>{/* 幅の制限なし */}
```

![maxWidth指定とfixedの場合での幅の変化のしかたを折れ線グラフで図式化したもの](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/8ad91c40-5be4-a760-6b96-30798203895d.png)

:::note info
ブレークポイントのデフォルトの設定（カスタマイズ可能です）
https://mui.com/material-ui/customization/breakpoints/

|指定子|意味|幅|
| - | - | -: |
| xs | extra-small | 0px |
| sm | small | 600px |
| md | medium | 900px |
| lg | large | 1200px |
| xl | extra-large | 1536px |

:::

# fixed &mdash; 段階的に幅変化

maxWidth を指定したとき（もちろん何も指定していないとき）には、下図の左側のように、最大値以下で流体的に幅が変化していましたが、

**fixed** を指定したときには、上図の右側の折れ線グラフように、ブレークポイントの幅を境界にして、段階的に幅が変化するようになります。

```tsx
<Container fixed>
```

# ヘッダーの幅固定

ヘッダの内容を、メインコンテンツと同じ幅に固定したいときにも Container が利用できます。

![ヘッダの幅を固定した例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/4c02708e-748e-4f89-235c-5b670b891ff3.png)

Appbar と Toolbar の役割は、以下のような分担になっています。

- **Appbar**
  - ヘッダの見た目（背景・影の設定・位置固定）
- **Toolbar**
  - ヘッダの内容を配置する

なので、 **Appbar &gt; Container &gt; Toolbar** とネストすることで、 Toolbar の幅が Container によって制限され、ヘッダ内容の幅を固定することができます。

![固定されたヘッダの構成の図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/a32b6d12-f1ff-6b9e-755e-dec5090320a2.png)

```tsx
<Stack bgcolor="#aaa">
  {/* ヘッダーUI */}
  <AppBar>
    <Container maxWidth="md">
      <Toolbar>
        <ButtonBase>Logogazo</ButtonBase>
        <ButtonBase sx={{ ml: "auto" }}>Menu</ButtonBase>
      </Toolbar>
    </Container>
  </AppBar>

  {/* AppBar の高さ分のスペース */}
  <Toolbar />

  {/* 幅固定・中央揃え のメインコンテンツ */}
  <Container maxWidth="md"  sx={{ marginY: 4 }}>
    <Paper sx={{ padding: 3 }}>
      <Typography>Container Width</Typography>
      {/* 以下略 */}
    </Paper>
  </Container>
</Stack>
```


# ほかにも応用できる

メインコンテンツ、ヘッダだけでなく、同じ位置・幅で揃えたいもの何にでも応用できます。

## たとえば、フッターメニュー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/53b6e821-95e3-bef1-e958-8da0e644b8f3.png)

```tsx
<Stack bgcolor="#aaa">
  {/* 略 */}

  {/* フッターUI */}
  <Box bgcolor="background.default">
    <Container maxWidth="md">
      <Box sx={{ p: 3 }}>
        <Typography>フッターフッター</Typography>
        <Typography>フッターのコンテンツ</Typography>
        {/* 以下略 */}
      </Box>
    </Container>
  </Box>
</Stack>
```

# disableGutters で左右の余白を除去

デフォルトでは左右に余白が追加されますが、そのせいで、「余白がある要素の中に余白のある要素が入る」ような形になった場合など、**余白を追加したくない** 場合には、 `disableGutters` を設定します。

```tsx
<Container disableGutters>
```

その他にも、MUI において余白がからむ設定は **gutter** (溝という意味) という単語が使われることが多いです。