CSSコンテナクエリについて

通常私たちがレスポンシブデザインを行うときは、ビューポート(viewport)に基づいてレイアウトを作成しますよね。
今回登場したコンテナクエリは、親要素のコンテナに基づいてレイアウトを作成することができます。

今日は、私自身の勉強も含めてコンテナクエリを説明&ご紹介していこうと思います。
デザインレイアウトやワークフローなどにどれくらい影響がでるのか、楽しみですね!

media queryの問題点について

私がこの仕事をし始めて7年~8年ほどになりますが、これまでレスポンシブ対応を行う際は、
ビューポート(viewport)の幅や高さ基づいて、デザインを変更し、スマホやタブレットなどに適応していました。

それが最近になって、CSSコンテナクエリというものがChrome Canaryで実験的な機能として実装されるようになりました。

従来のmedia queryでも問題ないよね?と思う方もいるかと思いますが
media queryでは実は実装者にとっては非常に厄介な問題があります。

たとえば以下のようなレイアウトを考えてみます。
お知らせなどのページでよく使用するレイアウトだと思います。

▼ウィンドウサイズが960px以上の見せ方

▼ウィンドウサイズが960px以下の見せ方

960px以下の場合はウィンドウサイズが小さくなる分、サイドバーを下に落とすことがよくあります。
ただし、サイドメニューが下に落ちる分メインブロック部分の表示範囲が広がるので、960px以上のときより1行に表示できるコンテンツの数を増やしてレイアウトを調整することがしばしばあります。

ただ、どんどん小さくなっていると結局3列にもどして、スマホのときは2列にして…といくつかの分岐を挟んで調整します。

これらをmedia queryを使ってCSSを書いた場合以下のような感じになります。

*, *:before, *:after {
     -webkit-appearance: none;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

.flex {
  display: flex;
  flex-wrap: wrap;
}

.container {
  justify-content:space-between;
  main {
    width: calc(100% - 360px);
    article {
      width: calc(100% / 3);
      padding: 10px;
      img {
        width: 100%;
        height: 200px;
        background-color: #ddd;
      }
      p {
        font-size: 14px;
        width: 100%;
      }
    }
  }
  side {
    width: 300px;
  }
}

@media (max-width: 961px) {
  .container {
    flex-direction: column;
    main {
      width: 100%;
      article {
        width: calc(100% / 4);
      }
    }
    side {
      width: 100%;
    }
  }
}

@media (max-width: 720px) {
  .container {
    main {
      article {
        width: calc(100% / 3);
      }
    }
  }
}

@media (max-width: 420px) {
  .container {
    flex-direction: column;
    main {
      width: 100%;
      article {
        width: calc(100% / 2);
      }
    }
    side {
      width: 100%;
    }
  }
}

ウィンドウズサイズに基づいているので、グリッド数を考慮しながらCSSを書かなければいけません。

Container Queriesを使ってみる

では、ここでCSSコンテナクエリを使ってみます。
Container Queriesは指定した親のブロック(セレクタ)の幅を基準にして
子要素のCSSを適応していくことができます。

今回の例でいうと「.container」の幅に応じて適応すればいいので、メインとサイドが上下になる場合のことを考慮する必要がなくなります。

実際にどのような形になるのか見てみましょう。

*, *:before, *:after {
     -webkit-appearance: none;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

.flex {
  display: flex;
  flex-wrap: wrap;
}

.container {
  justify-content:space-between;
  main {
    width: calc(100% - 360px);
    article {
      width: calc(100% / 3);
      padding: 10px;
      img {
        width: 100%;
        height: 200px;
        background-color: #ddd;
      }
      p {
        font-size: 14px;
        width: 100%;
      }
    }
  }
  side {
    width: 300px;
  }
}

@container (max-width: 961px) {
  .container {
    main {
      article {
        width: calc(100% / 4);
      }
    }
  }
}

@container (max-width: 420px) {
  .container {
    main {
      article {
        width: calc(100% / 2);
      }
    }
  }
}

これくらいシンプルに記載することができます。
便利ですね。

今回の例はすごくシンプルですが、複雑なものになってくるとmedia Queryだけだとレイアウト管理が難しくなってきます。

そのため、Container Queriesが重宝されるのです。

ブラウザー対応

現状はContainer QueriesはProposedの状況なので、どのブラウザーでも利用することができません。
chromeのchrome://flagsのみでお試しいただけます。
chromeのアドレスバーに「chrome://flags」を入力して、「Enable CSS Container Queries」と検索し、機能を有効にしてみてください。

早く各ブラウザで対応されるといいですね。
今後わたしたちのレスポンシブ対応やワークフローが変わりそうでワクワクします。

メンテナンスコストを考えても、確実に導入することで下がると思うので実装された際には積極的に取り組んでいきたいと思います。