14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

完全体となったContainer Queriesの所感の雑記

Last updated at Posted at 2023-02-13

Chrome 111 betaでついに、Style Container Queriesが対応されました。
Chrome 111 beta - Chrome Developers

今まではサイズのみ対応で、Container Queriesとして使い物になりませんでした。
しかし今回のベータ版のアップデートで style() 関数の対応しています。

前々からContainer Queriesは、CSS設計を変革させる機能だと思って非常に楽しみにしていました。ベータ版とはいえ、嬉しく思います。

追記: 2023年2月18日
まだ style(color: #000) 的な書き方は実装されていないので、完全体ではありませんでした。

Container Queriesで考えていたこと

Media Queries

「Media QueriesでCustom Propertiesを使いたい」というのをたまにTwitterなどで見かけます。
Media QueriesでCustom Propertiesを使えるようする仕様書などもあります。
ただうろ覚えなのですが、Media Queriesは独自で分離しており、:rootなどからCustom Propertiesを認識できるようにするのが大変、というのをどこかで見た気がします。
大変そうな処理なのでMedia Queriesよりも、Style Container Queriesで擬似的な実装ができないか考えていました。

:root {
  --viewport: initial;
  --viewport-sm: initial;
  --viewport-md: initial;
  
  container-name: root;
}

@media (800px > width) {
  :root {
    --viewport: md;
    --viewport-md: true;
  }
}

@media (400px > width) {
  :root {
    --viewport: sm;
    --viewport-sm: true;
  }
}

まずは :rootに対して、containerの名前空間を定義しておきます。 (root)
そしてCustom PropertiesをMedia Queriesで切り替えます。
これで下準備は完了です。
なお、ここでは --viewport と --viewport-** の2つのCustom Propertiesを定義しています。
--viewport は変数の値が切り替わるので、 特定のViewportに対してCSSが適用されます。
 --viewport-** はその指定のViewport以下に適用するためにCustom Propertiesを分離しています。

実際の記述を見てみましょう。

@container root style(--viewport: md) {
  .test {
    border: 8px solid #000;
  }
}

--viewport を指定しているので、400pxから800pxの間のみ、線が出るようになります。
もし800px以下で常に線を出したい場合は style(--viewport-md: true) と変えます。

まだ実験的な手法を考えて試しているだけなので、もう少しブラッシュアップが必要だと思いますが、これで擬似的にMedia QueriesをCustom Propertiesで扱うことができます。

pre と code

自分の個人ブログではprecodeを利用しています。
ただp要素の中のcodeは、装飾が必要ですが、pre codeはコードハイライト用のCSSを反映させるためにcodeのスタイルが不要になります。

<p>自分の個人ブログでは<code>code</code>を利用しています。</p>

<pre><code>// ここの`code`のスタイルはいらない</code></pre>

そのため、下記のようにCustom Propertiesのinitialテクニックを使用して、pre codeの場合はスタイルを表示させないようにしています。

code {
  --_code: initial;
  background: var(--_code, var(--color-gray-pale));
  border-radius: var(--_code, 4px);
  padding-block: var(--_code, 0.2em);
  padding-inline: var(--_code, 0.4em);
}
pre code {
  --_code: ;
}

ただContainer Queriesを使用すれば、もっとよくなりそうです。
試しに書きかえてみましたが、下記のコードでは動きませんでした。

code {
  --el-code: true;
  container-name: code;
}
pre code {
  --el-code: false;
}

@container code style(--el-code: true) {
  code {
    background: #eee;
    border-radius: 4px;
    padding: 0.2em 0.4em;
  }
}

上記のコードが動かない理由として、codeをContainer Queriesの「コンテナ」になってしまったからのようです。code要素の中にcode要素が入っていれば、子のcode要素のスタイルが変化しますが、コンテナになったセレクタはcontainerの基準になってしまうため、@containerQueries の適用範囲から外れてしまうようです。(this的なものが欲しい...)

そのため下記のように書きかえれば動作しますが、綺麗ではないですね。

:is(p, table) {
  --el-code: true;
  container-name: text;
}

@container text style(--el-code: true) {
  code {
    background: #eee;
    border-radius: 4px;
    padding: 0.2em 0.4em;
  }
}

pre要素のcode要素にスタイルが当たらないようにするなら、:not()で良くない?と思い直して書きかえました。
下記の方がスマートだし、Container Queriesいらんかった。

:not(pre) > code {
  background: #eee;
  border-radius: 4px;
  padding: 0.2em 0.4em;
}

pre と code の失敗から

Container Queriesの指定先は変化させることができない、という制限があるようなので使い所が難しいと思っていたのですが、ふと思いつきました。

CSSをコンポーネントでScopeできるんじゃね?

まずは適当なHTMLを用意します。

<div class="a">demo</div>

<div class="card">
  <div class="a">demo</div>
</div>

CSSは下記です。

:root {
  --scope: true;
}

.card {
  container-name: card;
}

@container card style(--scope: true) {
  .a {
    background: #faa;
    border-radius: 4px;
    margin: 1em 0;
    padding: 0.2em 0.4em;
  }
}

スクリーンショット 2023-02-13 10.43.34.png

.card のコンポーネントの中で Scope できました。

HTMLの要素をさらに増やします。

<h2 class="title">title</h2>
<div class="a">demo</div>
<p>本文のダミーテキスト</p>


<div class="card">
  <h2 class="title">title</h2>
  <div class="a">demo</div>
  <p>本文のダミーテキスト</p>
</div>

CSSは下記。

:root {
  --scope: true;
}

.card {
  container-name: card;
  border: 1px solid #000;
  padding: 1em;
}

@container card style(--scope: true) {
  .title {
    margin: 0;
    font-size: 1rem;
  }
  .a {
    background: #faa;
    border-radius: 4px;
    margin: 1em 0;
    padding: 0.2em 0.4em;
  }
  p {
    margin: 0;
    color: #aaa;
  }
}

スクリーンショット 2023-02-13 10.48.28.png

Container Queriesは名前空間も設定できるので、コンポーネントごとに container-nameプロパティを設定しておけば、Scopeとして扱うことができます。

Container Queriesは、まだChromeのベータ版しか対応されていませんが、やはり今後が楽しみな技術でした。

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?