prefer-container-queries について
コンテナに応じて変化する Tailwind のレスポンシブコンポーネントを作るためのガイダンスです。コンテナクエリの選択、移行、レビュー方法を扱います。
主な機能
- 01コンテナクエリを優先
- 02Tailwind のコンテナバリアントを解説
- 03ビューポートブレークポイントからの移行
- 04よくあるクエリの誤りを特定
- 05ビューポート単位のレイアウトを区別
活用シーン
- 01サイドバーやモーダル向けカードの作成
- 02コンポーネントのレスポンシブクラスの移行
- 03狭い領域でのレイアウト確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ flornkm/ skills --skill prefer-container-queriesインストール後、Claude Code で/prefer-container-queriesを入力して読み込まれたか確認します。
詳細
ビューポートブレークポイントよりコンテナクエリを優先する
コンポーネントはビューポートではなく、配置されている領域に応じて変化するべきです。サイドバー内のカードは、画面がどれほど大きくても幅が300px程度しかないことがあります。その場合、md:flex-rowのようなビューポートブレークポイントは、いつでも誤った結果になります。コンテナクエリなら、「ウィンドウの幅は?」ではなく、「自分の幅は?」とコンポーネント自身が判断できます。
レスポンシブなTailwindを書くときは、コンテナクエリをデフォルトにしてください。ビューポートブレークポイントは例外であり、基本ではありません。
仕組み
親要素をコンテナとして指定し、その子要素に@で始まるバリアントを使います。
<div class="@container">
<div class="flex flex-col @md:flex-row @md:gap-6">
<img class="w-full @md:w-48" />
<div class="@md:flex-1">...</div>
</div>
</div>
ここでの@md:は、ビューポートのサイズにかかわらず、「コンテナの幅が28rem以上のとき」を意味します。このカードは、クラスを一つも変更せずに、サイドバー、モーダル、全幅のグリッドで使えます。
つまずきやすいルールが2つあります。
@containerクラスは親要素に付けます。@md:バリアントは子孫要素に付けます。要素は自分自身のサイズをクエリできません。- コンテナバリアントは、最も近い
@containerを持つ祖先に反応します。スタイルが適用されない場合は、どのコンテナをクエリしているのか確認してください。
バリアント
Tailwind v4では、コンテナクエリがコアに組み込まれています。サイズは次のとおりです。
| バリアント | 最小幅 |
|---|---|
@3xs | 16rem(256px) |
@2xs | 18rem(288px) |
@xs | 20rem(320px) |
@sm | 24rem(384px) |
@md | 28rem(448px) |
@lg | 32rem(512px) |
@xl | 36rem(576px) |
@2xl | 42rem(672px) |
@3xl | 48rem(768px) |
@4xl | 56rem(896px) |
@5xl | 64rem(1024px) |
@6xl | 72rem(1152px) |
@7xl | 80rem(1280px) |
次のものも使用できます。
@max-md:は、コンテナサイズ未満でスタイルを適用します。@min-[475px]:は、既定のスケールが合わない場合に任意の値を指定できます。@container/sidebarと@md/sidebar:flex-rowを使うと、コンテナに名前を付け、ほかのコンテナを越えてツリーのより深い階層からクエリできます。
詳しくはこちらをご覧ください。
Tailwind v3では、同じ構文を使うために@tailwindcss/container-queriesプラグインが必要です。クラスを書く前に、Tailwindのバージョンを確認してください。
ビューポートブレークポイントを使うべき場面
次のものは変換しないでください。
- ページレベルのレイアウト。全体のグリッド、サイドバーの有無、ヘッダーやナビゲーションの挙動などです。これらは実際にビューポートに依存します。
- ビューポートを基準に配置される固定要素やスティッキー要素。たとえば、ボトムバーからサイドレールに変わる要素です。
- 画面サイズに連動する全体的なタイポグラフィのスケール。
こうしたレイアウト領域内にあるもの、つまりカード、フォーム、メディアオブジェクト、統計ブロック、テーブルとリストの切り替えなどには、コンテナクエリを使ってください。
既存コードの移行
- コンポーネントのレスポンシブクラス(
sm:、md:、lg:)を見つけます。 - コンポーネントのルート要素、または利用可能な領域を決めるラッパーに
@containerを追加します。 - ビューポートバリアントを、レイアウトを切り替える実際の幅に合ったコンテナバリアントに置き換えます。
md:をそのまま@md:に置き換えないでください。mdはビューポート幅768px、@mdはコンテナ幅448pxです。実際のブレークポイントを見つけるには、ウィンドウではなくコンテナのサイズを変えてください。 - コンポーネントを、モバイルのビューポート幅だけでなく、実際に使われる最も狭い状況(サイドバー、ドロワー、小さなグリッドセル)でテストします。
レビューで見つけるべき間違い
- サイドバーやモーダル内に表示されるコンポーネントに
md:flex-rowを使っている。実際の利用領域ではなくビューポートに応じて動作するため、積み重なったままになったり、崩れたりします。 @containerの祖先がない状態で@md:バリアントを使っている。何も表示されないまま適用されません。- 同じ要素に
@containerと@md:バリアントを指定している。要素は自分自身をクエリできません。バリアントを子要素に移すか、コンテナクラスを親要素に移してください。 - 作成された場所でしか正しく見えないコンポーネント。別の列に移すと崩れるなら、ビューポートに依存しています。