メディアクエリ無しで頑張るレスポンシブデザイン実装

## この記事の概要

メディアクエリをたくさん書いていると、どの幅のときにどのスタイルが当たるのか、段々分からなくなってきませんか？
私は分からなくなります。

というわけで、メディアクエリ無しでできる範囲のレスポンシブデザインを考えてみました。

:::note warn
コンテナクエリが普通に使えるようになればこの記事は不要になるかもしれません。
:::

## 完成物

次のような設定で作成しました。

- サイドバーとメイン要素
  - デスクトップでは2カラム、モバイルでは1カラム
- メイン要素内にはたくさんの子アイテム
  - 幅に応じてカラム数が変わる

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/5a0cadbe-9d9c-ca4a-7813-2ababdca273a.gif)

コードはこちらです。

```html:index.html
<!-- head要素などは省略 -->
<body>
  <div class="container">
    <h1 class="title">Layout with no media queries</h1>
    <div class="contents">
      <aside class="aside">
        <ul class="list">
          <li>foo</li>
          <li>bar</li>
          <li>baz</li>
          <li>qux</li>
          <li>quux</li>
        </ul>
      </aside>
      <main class="main">
        <div class="main-item">item 1</div>
        <div class="main-item">item 2</div>
        <div class="main-item">item 3</div>
        <div class="main-item">item 4</div>
        <div class="main-item">item 5</div>
        <div class="main-item">item 6</div>
        <div class="main-item">item 7</div>
        <div class="main-item">item 8</div>
        <div class="main-item">item 9</div>
        <div class="main-item">item 10</div>
        <div class="main-item">item 11</div>
        <div class="main-item">item 12</div>
      </main>
    </div>
  </div>
</body>
```

```css:style.css
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  height: 100%;
}

body {
  background-color: #f3f3f3;
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.container {
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
  padding: 16px;
}

.title {
  text-align: center;
}

.contents {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-inline: auto;
  padding-block: 16px;
  width: min(100%, 1024px);
}

.aside {
  align-self: flex-start;
  background-color: #fff;
  border-radius: 8px;
  flex-grow: 1;
  min-width: 224px;
  padding: 16px;
}

.list {
  padding-inline-start: 1rem;
}

.main {
  background-color: #fff;
  border-radius: 8px;
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  flex-grow: 1;
  min-width: 288px;
  padding: 16px;
}

.main-item {
  align-items: center;
  background-color: #ddd;
  border-radius: 4px;
  display: flex;
  height: 100px;
  justify-content: center;
}
```

## サイドバーとメイン要素のレイアウト

説明に必要な部分のコードだけを抜粋します。

```html:index.html
<div class="contents">
  <aside class="aside"></aside>
  <main class="main"></main>
</div>
```

```css:style.css
.contents {
  display: flex;
  flex-wrap: wrap;
}

.aside {
  align-self: flex-start;
  flex-grow: 1;
  min-width: 224px;
}

.main {
  flex-grow: 1;
  min-width: 288px;
}
```

1. `.contents`に`display: flex;`と`flex-wrap: wrap;`を指定し、`.aside`と`.main`にそれぞれ`min-width`を指定することで、基本は横並びにしつつ、`min-width`が確保できないときに折り返される
2. `.aside`と`.main`の両方に`flex-grow: 1;`を指定することで、可能な限り横幅が広がる
3. `.aside`に`align-self: flex-start;`を指定することで、縦に伸びなくなる（指定しないと、`.main`の高さに追従してしまう）
   1. `.contents`に`align-items: flex-start;`でも同じ効果が得られる

## メイン要素内のアイテムのレイアウト

説明に必要な部分のコードだけを抜粋します。

```html:index.html
<main class="main">
  <div class="main-item">item 1</div>
  <div class="main-item">item 2</div>
  <div class="main-item">item 3</div>
  <div class="main-item">item 4</div>
  <div class="main-item">item 5</div>
  <div class="main-item">item 6</div>
  <div class="main-item">item 7</div>
  <div class="main-item">item 8</div>
  <div class="main-item">item 9</div>
  <div class="main-item">item 10</div>
  <div class="main-item">item 11</div>
  <div class="main-item">item 12</div>
</main>
```

```css:style.css
.main {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
```

1. `.main`に`display: grid;`を指定し、`grid-template-columns`に`repeat`と`auto-fit`を組み合わせて指定する
1. `auto-fit`を指定することで、`.main-item`が幅200px以上になるように自動で計算して配置される
1. `gap`を指定することで、それぞれの子要素の間に常に一定の余白が空く
   1. `nth-child`などでmarginを指定すると、幅によって「何番目の要素に余白をつけるか」を制御しないといけなくなりがち

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489