k8o

Blog

公開: 2026年9月28日(月)約7分で読めます

Name-only container queriesでコンテナの名前だけを条件にスタイルを当てる

Name-only container queriesは、@containerに条件を書かず名前だけを指定するコンテナクエリです。Firefox 149とSafari 26.4に続いてChrome 148が対応し、Baseline 2026に加わりました。書き方、子孫セレクタとの違い、サイズクエリと併用するときの注意を整理します。

Newly availableName-only container queries2026年〜
  • Chrome148
  • Edge148
  • Firefox149
  • Safari26.4

はじめに

同じカードでも、本文の中では横並びに、サイドバーの中では縦積みにしたいことがあります。コンポーネントの見た目を、置かれた場所に応じて変える場面です。

これまでは、.sidebar .cardのような子孫セレクタを使うか、@container sidebar (width >= 0px)のように必ず真になる条件を付けたコンテナクエリを使っていました。子孫セレクタでは、配置先のクラス名がコンポーネントのCSSに入り込みます。コンテナクエリでは、使わない条件のためだけにcontainer-typeを指定することになります。

Name-only container queriesは、@container sidebarのように名前だけを書くコンテナクエリです。Firefox 149とSafari 26.4に続いてChrome 148が対応し、Baseline 2026に加わりました。

書き方

配置先の要素にcontainer-nameで名前を付け、@containerにその名前だけを書きます。

css
.sidebar {
  container-name: sidebar;
}

.card {
  display: flex;
  gap: 1rem;
}

@container sidebar {
  .card {
    flex-direction: column;
  }
}

@container sidebarの中のスタイルは、sidebarという名前の祖先を持つ要素に当たります。名前を持つ祖先は親でなくてもよく、何階層上にあっても構いません。

container-typeは指定しません。初期値のnormalのままでも対象になります。サイズクエリのためのcontainmentがかからないので、名前を付けても要素のレイアウトは変わりません。

container-nameには空白区切りで複数の名前を書けます。container-name: sidebar panelとした要素は、@container sidebarと@container panelのどちらの対象にもなります。

Playground

コンテナの名前でカードのレイアウトを切り替える

container-name-queries

親のcontainer-nameをラジオで切り替えると、中のカードに当たる@containerのブロックが変わる様子を確認できます。

親のcontainer-nameの値

親 (container-name: none)

k8o

Webフロントエンドのエンジニアです。

カードのスタイルは@container sidebarと@container footerに分けて書いてあり、親の名前と一致したほうが当たります。カードのクラスは変えていません。

なお、Firefoxではcontainer-nameをあとから変えても子孫のスタイルが更新されません。Bugzillaに報告されていますが、2026年9月時点のFirefox 156でも直っていません。

子孫セレクタとの違い

.sidebar .cardと書いても同じ要素に当たりますが、次の3点が変わります。

1つ目は詳細度です。@containerは詳細度を増やさないので、中に書いた.cardはクラス1つ分のままです。子孫セレクタではクラス2つ分になるので、上書きする側にも同じだけの詳細度が必要です。

css
/* クラス2つ分。.card-denseでは上書きできない */
.sidebar .card {
  gap: 0.5rem;
}

/* クラス1つ分。後ろに書いた.card-denseで上書きできる */
@container sidebar {
  .card {
    gap: 0.5rem;
  }
}

.card-dense {
  gap: 0;
}

2つ目は、配置先のセレクタを知らなくて済むことです。コンポーネントのCSSにはsidebarという名前しか出てきません。配置先が<aside>でも.drawerでも、container-name: sidebarを付ければ同じスタイルが当たります。

3つ目はShadow DOMです。shadow treeの中に書いた子孫セレクタは、shadow hostより外側の要素にはマッチしません。@container sidebarなら、shadow treeの中に書いても外側のsidebarを見つけられます。コンテナはflat treeの祖先から探されるためです。

html
<aside class="sidebar">
  <user-card>
    <template shadowrootmode="open">
      <style>
        .card {
          display: flex;
        }

        /* shadow treeの外にある.sidebarの名前に反応する */
        @container sidebar {
          .card {
            flex-direction: column;
          }
        }
      </style>
      <div class="card">...</div>
    </template>
  </user-card>
</aside>

サイズクエリと併用するとき

名前だけのクエリと条件付きのクエリでは、対象になるコンテナが違います。名前だけのクエリは、container-typeに関係なくその名前を持つ要素を見ます。サイズの条件を付けたクエリが見るのは、名前が一致し、かつサイズクエリのコンテナになっている要素だけです。

css
.sidebar {
  container-name: sidebar;
}

/* 当たる */
@container sidebar {
  .card {
    flex-direction: column;
  }
}

/* 当たらない。.sidebarはサイズクエリのコンテナではない */
@container sidebar (width > 20rem) {
  .card {
    flex-direction: row;
  }
}

1つのコンテナで名前とサイズの両方を見るなら、container: sidebar / inline-sizeのようにcontainer-typeも指定します。

名前とサイズを別々のコンテナで見るなら、@containerを入れ子にします。外側はsidebarという名前の祖先があるかを、内側は最も近いサイズクエリのコンテナの幅を見ます。

css
@container sidebar {
  @container (width > 20rem) {
    .card {
      flex-direction: row;
    }
  }
}

書けないこと

名前の否定は書けません。@container not sidebarは構文として無効で、ブロックごと無視されます。sidebarの外で当てたいスタイルは通常のルールとして書いておき、中でのスタイルを@container sidebarで上書きします。

@container sidebarのスタイルは、名前を付けた要素自身にも当たりません。コンテナクエリが見るのは祖先なので、@container sidebarの中に.sidebarのスタイルを書いても、さらに上にsidebarという名前の要素が無ければ効きません。

おわりに

Name-only container queriesで、配置先に付けた名前だけを条件にスタイルを書けるようになりました。container-typeも、必ず真になる条件も要りません。Firefox 149、Safari 26.4、Chrome 148が対応し、主要ブラウザで使えます。

読了率 0%
もくじ