container

コンテナにした親要素の幅に応じて、中の要素のスタイルを切り替えるアットルール。 ResizeObserverで幅を監視してクラスを付けていた処理を、CSSだけで書けます。

今の書き方

ラッパーに名前を付けてコンテナにし、その幅でスタイルを切り替えます。 画面幅ではなく置かれた場所の幅で決まるため、サイドバーでもメインでも同じ部品をそのまま使えます。

.card-wrapper {
  container: card / inline-size;
}

@container card (width >= 400px) {
  .card {
    display: grid;
    grid-template-columns: 120px 1fr;
  }
}
<div class="card-wrapper">
  <article class="card">
    <img src="thumbnail.jpg" alt="" />
    <div>...</div>
  </article>
</div>

以前の書き方

メディアクエリは画面幅しか分からないため、置かれた場所の幅で切り替えるにはJavaScriptが必要でした。 ResizeObserverでラッパーの幅を監視し、400px以上ならカードにクラスを付けます。

.card.is-wide {
  display: grid;
  grid-template-columns: 120px 1fr;
}
<div class="card-wrapper">
  <article class="card">
    <img src="thumbnail.jpg" alt="" />
    <div>...</div>
  </article>
</div>
const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const card = entry.target.querySelector('.card')
    card.classList.toggle('is-wide', entry.contentRect.width >= 400)
  }
})

for (const wrapper of document.querySelectorAll('.card-wrapper')) {
  observer.observe(wrapper)
}

置き換えるときの注意点

  • コンテナ自身には、@containerのスタイルは当たりません。 切り替えたい要素の外側にラッパーを置き、ラッパーをコンテナにします。
  • inline-sizeを指定した要素は、中身から幅が決まらなくなります。 inline-blockや、中身の幅で大きさが決まるFlexboxの子要素に指定すると、幅が0になります。 ブロック要素のように、幅が外側から決まる要素に指定します。
  • container-type: sizeを指定すると、高さも中身から決まらなくなります。 高さを指定していない要素には、inline-sizeを使います。
  • 名前のない@containerは、いちばん近いコンテナを見ます。 コンテナが入れ子になると意図しない幅で切り替わるため、名前を付けて対象を決めておきます。
  • コンテナの幅を基準にした単位(cqiなど)も使えます。 文字の大きさや余白を、置かれた場所の幅に合わせられます。

フォールバック

対象の5ブラウザはすべて対応済みなので、通常は以前の書き方を残す必要はありません。 狭いときのスタイル(縦並び)を基本にしておけば、対応していないブラウザでは縦並びのまま表示されます。 対応していないブラウザでも横並びにする必要がある場合だけ、以前の書き方のCSSを残し、JavaScriptを対応していないブラウザでだけ動かします。

// コンテナクエリに対応していないブラウザでだけ、以前の書き方のクラスを付ける
if (!CSS.supports('container-type', 'inline-size')) {
  const observer = new ResizeObserver((entries) => {
    for (const entry of entries) {
      const card = entry.target.querySelector('.card')
      card.classList.toggle('is-wide', entry.contentRect.width >= 400)
    }
  })
  for (const wrapper of document.querySelectorAll('.card-wrapper')) {
    observer.observe(wrapper)
  }
}

Browser Support

  • Chrome

    v105+
    2022-09-02
  • Edge

    v105+
    2022-09-01
  • Safari

    v16+
    2022-09-12
  • Safari (iOS)

    v16+
    2022-09-12
  • Firefox

    v110+
    2023-02-14

機能名やコードで検索できます

例:aspect-ratio、:has()、padding-top

別の言葉や、プロパティ名で試してください

検索を読み込めませんでした