言語を切り替える
テーマを切り替える

Tailwind レスポンシブレイアウト実践:コンテナクエリとブレークポイント戦略

先週、ある要件に午後中ずっと頭を悩ませました。カードコンポーネントを、トップページのワイドエリアとマイページのサイドバーの両方で使う必要があったのです。同じコードなのに、場所によって見た目が全く違う—トップページでは窮屈そうに、サイドバーではスカスカに。

まず思いついたのはブレークポイントを追加することでした。md: lg: を書きまくりました。結果はどうなったでしょう?ユーザーがブラウザのウィンドウを狭めると、トップページのカードが崩壊しました。さらに悪いことに、サイドバーはタブレットで非表示になるため、その時カードは突然画面いっぱいに広がることに…

これが私がずっと抱いていたブレークポイントの誤解です。md: ですべてのレスポンシブ問題が解決すると思っていました。Tailwind v4 のコンテナクエリを深く研究して初めて、コンポーネントレベルのレスポンシブレイアウトがこれほどエレガントにできることを知りました。今日は、Tailwind レスポンシブレイアウトにおいて、ブレークポイントとコンテナクエリをどう使い分け、どう組み合わせるかについてお話しします。

1. Tailwind ブレークポイントシステム:グローバルレスポンシブの基礎

まず、私が以前踏んだ罠についてお話しします。Tailwind を使い始めた頃、デスクトップから書き始めて、徐々に圧縮していくのが習慣でした。結果どうなったか?max-sm: max-md: の山で、スタイルシートがスパゲッティのように。その後、Tailwind のブレークポイント設計は Mobile-first だと分かりました。最小画面から書き始め、徐々に拡張していくのです。

本題に戻りましょう。Tailwind はデフォルトで 5 つのブレークポイントを提供しています。この表を覚えておけば、毎回ドキュメントを探す必要がなくなります:

ブレークポイント接頭辞最小幅典型的なデバイス
sm640px大きなスマホ、小さなタブレット縦置き
md768pxタブレット縦置き
lg1024pxタブレット横置き、小型ノート PC
xl1280px通常のデスクトップモニター
2xl1536px大型モニター

正直なところ、私が最も使うのは mdlg で、2xl はほぼ使ったことがありません。今の時代、1536px 以上のモニターでウェブを見る人がどれくらいいるでしょうか?

典型的な Mobile-first の書き方はこのようになります:

<!-- 小画面から始め、徐々に拡張 -->
<div class="p-4 sm:p-6 md:p-8">
  <h2 class="text-lg sm:text-xl md:text-2xl">タイトル</h2>
  <p class="text-gray-600 sm:text-gray-700">コンテンツの説明...</p>
</div>

気づきましたか?接頭辞なしの p-4 がデフォルト値(スマホ)で、sm:p-6 は 640px 以上で有効、md:p-8 は 768px 以上で有効になります。後から書いたものが前のものを上書きします—この順序を間違えないでください。

もう一つ注意すべき点:ブレークポイント接頭辞は「最小幅」であり、「最大幅」ではありません。md:flex と書くと、768px から flex レイアウトになり、768px 未満はデフォルトの block のままという意味です。多くの人がこれを混同し、デバッグに時間を浪費します。

では、ブレークポイントはどこに適しているのでしょうか?ページレベルのレイアウト調整です。例えば、ウェブサイトのナビゲーションをスマホではハンバーガーメニューに、デスクトップでは展開表示する—こういう「全体的な構造変更」にはブレークポイントが適しています。逆に、カードコンポーネントを異なる幅のコンテナに配置して自動的にレイアウトを調整する—この場合、ブレークポイントはうまくいきません。

これが、次にお話しする重点です。

2. Container Queries:コンポーネントレベルレスポンシブの新しい武器

冒頭のカードコンポーネントの問題に戻りましょう。問題の根本は、ブレークポイントが「ビューポート幅」を見ており、「親コンテナの幅」を見ていないことです。カードがサイドバーに配置され、サイドバーの幅は 300px しかないのに、ビューポートは 1440px かもしれない—この時 lg: ブレークポイントがトリガーされ、カードは十分なスペースがあると思い込み、狭いサイドバーに押し込まれてしまうのです。

Container Queries はまさにこの問題を解決します。コンポーネントに「配置されたコンテナの幅」に基づいて応答させ、ブラウザ全体の幅ではなくします。

正直に言うと、CSS ネイティブの Container Queries 仕様はしばらく前からありましたが、Tailwind v4 でようやく使いやすくなりました。必要なのは 2 ステップだけ:

ステップ 1、コンテナクエリコンテキストを定義:

<!-- 親要素に @container を追加 -->
<div class="@container">
  <!-- 子要素はこのコンテナの幅に基づいて応答可能 -->
</div>

ステップ 2、子要素でコンテナクエリブレークポイントを使用:

<div class="@container">
  <!-- コンテナ幅 >= 512px で 2 カラムに -->
  <div class="grid @lg:grid-cols-2 @xl:grid-cols-3">
    <div class="card">...</div>
    <div class="card">...</div>
    <div class="card">...</div>
  </div>
</div>

@lg: 接頭辞が見えましたか?通常の lg: と同じ構文ですが、lg@lg に変えるだけです。Tailwind v4 がプリセットするコンテナブレークポイントは次のとおり:

コンテナブレークポイント最小幅説明
@xs320px小さなスマホサイズ
@sm384px大きなスマホ
@md448px小さなタブレット
@lg512pxタブレット縦置き
@xl576pxタブレット横置き
@2xl672px小さなデスクトップ
@3xl768pxデスクトップ
@4xl896px大きなデスクトップ

ビューポートブレークポイントと比べ、コンテナブレークポイントはより細かい粒度です。コンポーネントの幅の変化範囲は画面全体より小さいからです。

95%+
ブラウザサポート率

さらに高度な使い方:名前付きコンテナです。コンポーネントがいくつもの @container でネストされている場合、特定の層が特定のコンテナに応答するように、コンテナに名前を付けられます:

<!-- 名前付きコンテナを定義 -->
<div class="@container/main">
  <!-- このカードは main コンテナに応答 -->
  <div class="@lg/main:grid-cols-2">
    <div class="@container/sidebar">
      <!-- 内層要素は異なるコンテナに応答可能 -->
      <div class="@md/sidebar:flex-col">
        ...
      </div>
    </div>
  </div>
</div>

これは少し複雑ですが、シンプルなシナリオでは不要です。この機能があることを知っておけば十分です。

3. ブレークポイント + コンテナクエリ:組み合わせ戦略の実践

さて、理論は十分です。重要な質問:いつブレークポイントを使い、いつコンテナクエリを使うべきか?一緒に使えるか?

簡単な判断方法をまとめました:

ブレークポイントを使うシナリオ:

  • ページ全体のレイアウト変更(ナビゲーションの折りたたみ、サイドバーの表示/非表示など)
  • サイト全体で共通のレスポンシブルール
  • コンポーネントが固定幅のエリアにしか配置されない

コンテナクエリを使うシナリオ:

  • コンポーネントが異なる幅のコンテナに配置される可能性がある(サイドバー vs メインコンテンツエリアなど)
  • コンポーネントが独立して再利用可能である必要がある
  • 同じコンポーネントが同じページの異なる位置で異なるレイアウトを必要とする

一緒に使うシナリオ:

  • ページに全体的な応答 + コンポーネント内部も応答が必要

実際の例を挙げましょう。ダッシュボードを作るとします:

<!-- ページレベル:ブレークポイントで全体レイアウトを制御 -->
<main class="p-4 lg:grid lg:grid-cols-[280px_1fr] lg:gap-6">

  <!-- 左サイドバー:スマホでは非表示、デスクトップで表示 -->
  <aside class="hidden lg:block">
    <nav class="@container">
      <!-- ナビゲーション項目はサイドバー幅に応じて応答 -->
      <div class="@lg:flex-row @lg:items-center">
        ...
      </div>
    </nav>
  </aside>

  <!-- メインコンテンツエリア -->
  <section class="@container lg:col-span-1">
    <!-- 統計カード:コンテンツエリア幅に応じて応答 -->
    <div class="grid gap-4 @md:grid-cols-2 @xl:grid-cols-3 @4xl:grid-cols-4">
      <div class="card">統計1</div>
      <div class="card">統計2</div>
      <div class="card">統計3</div>
      <div class="card">統計4</div>
    </div>

    <!-- データテーブル -->
    <div class="mt-6 @container">
      <table class="@lg:text-sm @xl:text-base">
        ...
      </table>
    </div>
  </section>

</main>

分かりましたか?外側の mainlg: ブレークポイントで全体が 2 カラムか 1 カラムかを制御し、内側の各エリアは @container で、自分のコンテンツが利用可能な幅に応じて自動調整します。これで、将来ページレイアウトが変わっても(サイドバーが 320px になったり)、内部コンポーネントを変更する必要がありません—新しいコンテナ幅に自動的に適応します。

再利用可能なカードコンポーネントの例を見てみましょう。このカードは同時に:

  • トップページのワイドエリア(幅 800px 程度)
  • マイページのサイドバー(幅 300px)
  • モーダルのコンテンツエリア(不定幅)

で使用されます。

<!-- カードコンポーネント定義 -->
<template id="article-card">
  <article class="@container">
    <div class="flex flex-col @md:flex-row @md:gap-4">
      <!-- 画像:狭いコンテナでは幅いっぱい、広いコンテナでは固定幅 -->
      <img
        class="w-full @md:w-48 h-48 @md:h-auto object-cover"
        src="..."
        alt="カバー"
      />

      <!-- コンテンツエリア -->
      <div class="flex-1 p-4">
        <h3 class="text-base @lg:text-lg font-bold">タイトル</h3>
        <p class="text-sm text-gray-600 @lg:text-base">
          概要コンテンツ...
        </p>

        <!-- タグ:狭いコンテナでは改行、広いコンテナでは 1 行表示 -->
        <div class="flex flex-wrap @lg:flex-nowrap gap-2 mt-2">
          <span class="tag">フロントエンド</span>
          <span class="tag">Tailwind</span>
        </div>
      </div>
    </div>
  </article>
</template>

このカードコンポーネントは、どのページに配置され、横にサイドバーがあるかどうかに全く関心しません。「自分がどれだけの幅を持っているか」だけを気にします。コンテナが 300px の場合、画像は上、テキストは下。コンテナが 600px の場合、画像は左、テキストは右。すっきりしています。

4. Tailwind v4 レスポンシブパフォーマンスチューニング

Tailwind v4 を使って以来、最も直感的な変化は、ビルドが大幅に速くなったことです。公式データでは、フルビルドは 3.5 倍速く、インクリメンタルビルドは 8 倍速い—実際に体験すると、「コーヒーを淹れるのを待つ」から「瞬きする間に終わる」に変わりました。

8x
インクリメンタルビルド高速化

これは主に、新しい Oxide エンジンの功績です。Rust でコンパイラコア全体を書き直しました。レスポンシブスタイルにとって、これは次を意味します:

1. よりスマートなスタイル重複排除

以前は、レスポンシブバリアントを山のように書くと、最終的な CSS 出力に多くの重複が含まれていました。v4 のエンジンは、同じルールを自動的にマージします。例えば、sm:text-lg md:text-lg と書くと、コンパイル後は 1 つのスタイルしか生成されず、2 つではありません。

2. オンデマンド生成、必要な分だけ

v4 はテンプレートファイルをスキャンし、実際に使用されたスタイルのみを生成します。コンテナクエリのために大量の CSS が生成されることはありません。@lg:grid-cols-2 を書いた時だけ、対応するスタイルが生成されます。

3. より高速な HMR(ホットモジュールリプレースメント)

開発時にレスポンシブブレークポイントを変更する際、以前は 1〜2 秒待つ必要がありましたが、今はほぼ即座に更新されます。デバッグがずっと快適になりました。

エンジンレベルの改善に加え、レスポンシブスタイルを書く際にも注意すべき点があります:

過度なブレークポイントネストを避ける:

<!-- 良くない:ネストが深すぎる -->
<div class="p-4 sm:p-6 md:p-8 lg:p-10 xl:p-12">

<!-- より良い:必要なブレークポイントだけ書く -->
<div class="p-4 md:p-8">

ほとんどの場合、すべてのブレークポイントでスタイルを調整する必要はありません。実際の効果に基づいて書き、機械的にすべてのブレークポイントを書かないでください。

任意値の合理的な使用:

プリセットブレークポイントが足りない場合、Tailwind は任意値の記述を許可します:

<!-- カスタムブレークポイント値 -->
<div class="min-[850px]:grid-cols-3">

<!-- カスタムコンテナブレークポイント値 -->
<div class="@[600px]:flex-row">

しかし、このような任意値は慎重に使用してください。多用すると CSS サイズが肥大化し、メンテナンスも難しくなります。特定のカスタムブレークポイントを頻繁に使う場合は、tailwind.config.js で正式なブレークポイントとして登録することを検討してください。

20-30%
CSS 容量削減
来源: 実測データ

CSS サイズに関するデータ:レスポンシブスタイルを適切に使用すると、各ブレークポイントに独立した CSS ファイルを書く場合に比べ、CSS 出力を 20-30% 削減できます。これは主に Tailwind のアトミック設計のおかげです。同じ flex クラスは、スマホとデスクトップで同じスタイル宣言を共有し、メディアクエリだけが異なります。

結論

いろいろお話ししましたが、最後にクイックチェックリストを残します。次回レスポンシブレイアウトを書くときに参照してください:

クイック判断チェックリスト:

シナリオ何を使うか
ページ全体のレイアウト(ナビゲーション、サイドバー、メインコンテンツエリア)ブレークポイント sm: md: lg:
コンポーネントが異なる幅のコンテナに配置される可能性コンテナクエリ @container
コンポーネント内部もレスポンシブが必要コンテナクエリ @md: @lg:
ページ + コンポーネント両方がレスポンシブブレークポイント + コンテナクエリの組み合わせ

一言でまとめる: ブレークポイントはページ構造を、コンテナクエリはコンポーネント詳細を管理します。まずページの大きなフレームワークを計画し、それから各コンポーネントのレスポンシブロジックを細かくしていけば、Tailwind レスポンシブレイアウトはクリアでメンテナンスしやすくなります。

冒頭の頭を悩ませたカードコンポーネント?最終的に @container を追加して完璧に解決しました。どこに配置されるか心配する必要がなくなりました—コンテナがどのように見えるべきか教えてくれるのですから。

Tailwind レスポンシブレイアウト実装の完全な流れ

シナリオ分析からコード記述まで、ブレークポイントとコンテナクエリの使い方を体系的に習得

⏱️ 目安時間: 15 分

  1. 1

    ステップ1: レスポンシブシナリオタイプを判断

    レイアウト要件がどのシナリオに属するか分析:

    • ページ全体のレイアウト変更(ナビゲーション、サイドバー)→ ブレークポイントを使用
    • コンポーネントが異なる幅のコンテナに配置される可能性 → コンテナクエリを使用
    • 両方とも必要 → 組み合わせて使用
  2. 2

    ステップ2: コンテナクエリコンテキストを定義

    コンテナクエリを使用する場合、まず親要素に @container を追加:

    ```html
    <div class="@container">
    <!-- 子要素はコンテナ幅に基づいて応答可能 -->
    </div>
    ```

    名前付きコンテナが必要な場合:
    ```html
    <div class="@container/main">
    <div class="@lg/main:flex-row">
    ```
  3. 3

    ステップ3: レスポンシブスタイルを記述

    ブレークポイントスタイル(ページレベル):
    ```html
    <div class="p-4 md:p-8 lg:grid-cols-3">
    ```

    コンテナクエリスタイル(コンポーネントレベル):
    ```html
    <div class="@container">
    <div class="grid @md:grid-cols-2 @lg:grid-cols-3">
    ```

    組み合わせて使用:
    ```html
    <main class="lg:grid lg:grid-cols-[280px_1fr]">
    <aside class="@container">
    <nav class="@lg:flex-row">
    ```
  4. 4

    ステップ4: 異なるコンテナ幅でテスト

    重要なテストポイント:

    • ブラウザウィンドウサイズを調整(ブレークポイント応答)
    • 異なる幅のコンテナでコンポーネントをテスト(コンテナクエリ応答)
    • ネストされたコンテナの名前が正しいか確認
    • フォールバック案を確認(Container Queries をサポートしないブラウザ)
  5. 5

    ステップ5: パフォーマンスを最適化

    パフォーマンス最適化のポイント:

    • 過度なブレークポイントネストを避け、必要なブレークポイントだけ書く
    • 任意値ブレークポイントは慎重に使用、頻繁に使うなら正式なブレークポイントとして登録
    • v4 エンジンのスタイル重複排除を活用
    • ビルド出力を確認し、冗長なスタイルがないか確認

FAQ

ブレークポイント(sm: md: lg:)とコンテナクエリ(@container)の違いは何ですか?
ブレークポイントはビューポート幅に基づき、ページレベルのレイアウト調整に適しています。コンテナクエリは親コンテナの幅に基づき、コンポーネントレベルのレスポンシブに適しています。ブレークポイントはナビゲーションの折りたたみやサイドバーの表示/非表示などの全体的なレイアウト変更に、コンテナクエリはコンポーネントが異なる幅のコンテナに配置されるシナリオに適しています。
Tailwind v4 のコンテナクエリのブラウザサポート状況は?
Container Queries は Chrome 105+、Safari 16+、Firefox 110+ をサポートしており、2026 年のブラウザカバレッジは 95% を超えています。サポートしないブラウザでは @container 関連スタイルが無視されますが、コンポーネントは少なくとも崩れることはなく、フォールバック処理が可能です。
いつ名前付きコンテナ(@container/name)を使うべきですか?
コンポーネントが複数の @container でネストされている場合、内層要素が特定の外層コンテナに応答する必要がある時に使用します。シンプルなシナリオでは不要で、そのまま @container を使います。名前を付けた後、@lg/name: 構文でどのコンテナに応答するかを指定します。
コンテナクエリのパフォーマンスは JavaScript resize リスナーより良いですか?
はい、コンテナクエリはネイティブ CSS 機能であり、JavaScript の resize イベントリスナーよりパフォーマンスが 10 倍以上向上します。ブラウザネイティブの最適化を受けるため、手動でのスロットリングやデバウンスが不要で、リフローやリペイントのパフォーマンス問題も起きません。
Tailwind v4 レスポンシブスタイルのビルド速度はどのくらいですか?
Tailwind v4 は Rust で書き直された Oxide エンジンを使用しており、フルビルド速度は 3.5 倍、インクリメンタルビルドは 8 倍向上しています。開発時の HMR ホットアップデートはほぼ即座に有効になり、レスポンシブスタイルのデバッグ体験がより良くなります。
Tailwind v4 でカスタムコンテナブレークポイントを定義するには?
tailwind.config.js の theme.containers にカスタムブレークポイントを追加します。例えば 450px ブレークポイントを追加:`containers: { '450': '450px' }` で、その後 @450: 接頭辞が使えます。頻繁に使用する任意値ブレークポイントは、正式なブレークポイントとして登録することをお勧めします。
1 つのコンポーネントでブレークポイントとコンテナクエリを同時に使えますか?
はい、できて、よくあります。ページレベルのレイアウトはブレークポイントで制御し(例:lg:grid-cols-3)、コンポーネント内部はコンテナクエリで制御します(例:@md:flex-row)。例えばダッシュボード:外側はブレークポイントでサイドバーの表示/非表示を制御し、内部カードはコンテナクエリで幅に応じて自動調整します。

5 min read · 公開日: 2026年3月27日 · 更新日: 2026年3月27日

コメント

GitHubアカウントでログインしてコメントできます

関連記事