



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









「スマホで見るとレイアウトが崩れる」「パソコンとスマホで別々のCSSを書くのが面倒」——Web制作をはじめた多くの方がこの壁にぶつかります。その解決策がCSSメディアクエリです。メディアクエリを使えば、画面の幅・向き・カラースキームなどの条件に合わせてスタイルを切り替えられます。
この記事では、メディアクエリの基本構文からモバイルファースト設計、ブレイクポイントの決め方、実践的なレイアウト例、そしてダークモード対応や2026年現在で普及が進むコンテナクエリまで、初心者〜中級の制作者が現場で使える知識をまとめて解説します。コードはすべてコピペで動くように書いてあるので、手元の環境で試しながら読み進めてください。
メディアクエリをきちんと理解すると、ゼロから書くコードの量が減り、デザインの変更にも強い柔軟なCSSが書けるようになります。まずは基本から順を追って確認していきましょう。
メディアクエリ(Media Query)とは、CSS3で導入された機能で、「どんな環境でページが表示されているか」という条件をCSSの中で判定するしくみです。画面幅・解像度・向き・ユーザー設定などを条件として指定し、その条件を満たす場合だけ特定のスタイルを適用できます。レスポンシブWebデザインの土台となる技術であり、1枚のHTMLファイルでスマホ・タブレット・PCすべてに対応したレイアウトを実現するために不可欠です。
メディアクエリは @media ルールで始めます。括弧内に条件(メディア特性)を書き、その後の波括弧にスタイルを書きます。
/* 画面幅が768px以上のとき適用 */
@media (min-width: 768px) {
.container {
max-width: 1100px;
margin: 0 auto;
}
}
/* 画面幅が480px以下のとき適用 */
@media (max-width: 480px) {
.nav {
display: none;
}
}
@media の後に書く screen などのメディアタイプは現在では省略するのが一般的です。screen(画面)・print(印刷)・all(すべて)が主な種類ですが、印刷用スタイルを分けたい場合以外は省いて問題ありません。複数の条件は and で繋ぎ、「または」は ,(カンマ)を使います。
/* 768px以上かつ1200px以下 */
@media (min-width: 768px) and (max-width: 1200px) {
.sidebar {
width: 280px;
}
}
/* 480px以下または1400px以上(どちらか) */
@media (max-width: 480px), (min-width: 1400px) {
.hero {
padding: 40px 20px;
}
}
上の例では and で繋いだ場合は「両方の条件が真」のとき、カンマで繋いだ場合は「どちらかの条件が真」のときにスタイルが適用されます。
min-width は「画面幅がこの値以上のとき」という条件です。小さい画面のスタイルをベースに書いておき、画面が広くなるにつれて追加・上書きしていくモバイルファーストアプローチと相性が良いのが特徴です。
/* ベース(全画面共通、主にモバイル想定) */
.card {
display: block;
padding: 16px;
}
/* 768px以上(タブレット〜PC)になったら2列に */
@media (min-width: 768px) {
.card-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24px;
}
}
/* 1024px以上(PC)になったら3列に */
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, 1fr);
}
}
max-width は「画面幅がこの値以下のとき」という条件です。PCのスタイルをベースに書いておき、画面が狭くなったときに上書きするデスクトップファーストのアプローチと対応します。古くからあるサイトのリニューアルや、既存のPC向けCSSに後からレスポンシブを追加するケースで使われます。
/* ベース(PC向け) */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
/* 767px以下(タブレット以下)なら2列 */
@media (max-width: 767px) {
.card-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 480px以下(スマホ)なら1列 */
@media (max-width: 480px) {
.card-grid {
grid-template-columns: 1fr;
}
}
新規制作では min-width(モバイルファースト) を推奨します。理由は3つあります。第一に、モバイルのトラフィックが全体の過半数を占める現在、最も重要な環境を優先して設計できます。第二に、コードが上書きの連鎖になりにくく保守しやすいです。第三に、ブラウザが先にシンプルなスタイルを読み込むため、低スペックのモバイル端末でのパフォーマンスに有利です。
モバイルファーストとは、最初にスマートフォンの表示を設計し、画面が広くなるにつれてレイアウトを拡張していく考え方です。CSSの記述量を減らせるだけでなく、何を一番伝えたいかという情報設計の整理にもつながります。@media なしのセレクタがモバイルの基本スタイルを担い、min-width のメディアクエリがそれを上書き・拡張します。
/* モバイルファーストの典型例 */
/* ベース:縦1列、フォント小さめ */
.hero {
padding: 32px 16px;
text-align: center;
}
.hero__title {
font-size: 1.6rem;
line-height: 1.4;
}
.hero__image {
width: 100%;
margin-top: 24px;
}
/* タブレット以上:横並びにする */
@media (min-width: 768px) {
.hero {
display: flex;
align-items: center;
gap: 40px;
padding: 60px 40px;
text-align: left;
}
.hero__title {
font-size: 2.4rem;
}
.hero__image {
width: 45%;
margin-top: 0;
flex-shrink: 0;
}
}
/* デスクトップ以上:さらに大きく */
@media (min-width: 1200px) {
.hero {
padding: 80px 60px;
max-width: 1300px;
margin: 0 auto;
}
.hero__title {
font-size: 3rem;
}
}
このように書くと、スマホでは最小限のスタイルだけロードされ、タブレット・PCでは必要なスタイルが順番に追加されます。デスクトップファーストで書くと逆に「スマホでは打ち消し」が多発し、コードが複雑になりがちです。
ブレイクポイントとは、レイアウトが切り替わる画面幅の境界値のことです。「iPhoneが375px、iPadが768px」といったデバイスの解像度でブレイクポイントを設定する方法は、かつてよく使われました。しかし現在は端末の種類が多様すぎるため、デザインが崩れ始める幅を見ながら判断するのが定石です。デザインツールでプレビューしながら、「この幅で横並びが窮屈になってきた」という点をブレイクポイントに設定します。
とはいえ、ゼロから決めるのが難しい場合の参考として、2026年現在の主要フレームワークが採用する数値を示します。
Tailwind CSSは sm:640、md:768、lg:1024、xl:1280、2xl:1536 という区切りを採用しています。この数値はメジャーなフレームワークが長年の実績から採用したものなので、迷ったときの出発点として参考にする価値があります。ただし最終的には自分のデザインに合わせて調整することが大切です。
プロジェクトが大きくなると、数値が各所に散らばって保守が大変になります。CSSカスタムプロパティ(変数)で管理しておくとすっきりします。ただし、メディアクエリの条件値にはカスタムプロパティを直接使えない制約があるため、次のように定数としてコメントで管理するか、PostCSSやSassのmixinを使う方法が現実的です。
/*
ブレイクポイント定義(コメントで共有)
--bp-sm: 640px
--bp-md: 768px
--bp-lg: 1024px
--bp-xl: 1280px
*/
/* 使用箇所では数値を直接書く(カスタムプロパティはmq条件に使えない) */
@media (min-width: 768px) { /* --bp-md */ }
@media (min-width: 1024px) { /* --bp-lg */ }
もっともよく使うパターンのひとつがナビゲーションの切り替えです。スマホではハンバーガーアイコンを表示し、PCでは横並びのリンクを表示します。
<header class="site-header">
<a href="/" class="logo">LOGO</a>
<button class="hamburger" aria-label="メニューを開く">☰</button>
<nav class="global-nav">
<ul>
<li><a href="/about">About</a></li>
<li><a href="/works">Works</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
/* ベース(モバイル) */
.site-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
}
.global-nav {
display: none; /* モバイルでは非表示 */
}
.hamburger {
display: block;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
}
/* PC(768px以上) */
@media (min-width: 768px) {
.global-nav {
display: block; /* ナビを表示 */
}
.global-nav ul {
display: flex;
gap: 32px;
list-style: none;
margin: 0;
padding: 0;
}
.hamburger {
display: none; /* ハンバーガーを非表示 */
}
}
商品一覧やブログ記事一覧のカードグリッドをレスポンシブにする典型例です。CSS Gridと repeat() を組み合わせると、メディアクエリ側の変更が最小限で済みます。
/* モバイル:1列 */
.card-grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
/* タブレット:2列 */
@media (min-width: 640px) {
.card-grid {
grid-template-columns: repeat(2, 1fr);
gap: 24px;
}
}
/* PC:3列 */
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, 1fr);
gap: 32px;
}
}
/* 大型モニター:4列 */
@media (min-width: 1280px) {
.card-grid {
grid-template-columns: repeat(4, 1fr);
}
}
auto-fill や auto-fit を使うと、メディアクエリなしで自動的に折り返すグリッドも作れます。ただし列数を厳密にコントロールしたい場合はメディアクエリで明示する方が安全です。
見出しのフォントサイズをモバイルとPCで変えるのは基本中の基本です。clamp() と組み合わせると、ブレイクポイントを超えた中間の幅でも滑らかに変化します。
/* メディアクエリだけで切り替える方法 */
.section-title {
font-size: 1.5rem;
}
@media (min-width: 768px) {
.section-title {
font-size: 2rem;
}
}
@media (min-width: 1200px) {
.section-title {
font-size: 2.8rem;
}
}
/* clamp()を使って滑らかに変化させる方法 */
.section-title-fluid {
/* 最小1.5rem → ビューポートに応じて → 最大3rem で変化 */
font-size: clamp(1.5rem, 3vw + 1rem, 3rem);
}
clamp(最小値, 推奨値, 最大値) を使った流動的なタイポグラフィは、メディアクエリを複数書かなくて良いメリットがあります。ただし細かい制御が難しいため、多くの場合はメディアクエリと併用します。
スマートフォンやタブレットでは、ユーザーが端末を横にして使うことがあります。orientation を使うと、縦向き(portrait)と横向き(landscape)でスタイルを切り替えられます。
/* 縦向きのとき */
@media (orientation: portrait) {
.hero-image {
height: 40vh;
object-fit: cover;
}
}
/* 横向きのとき */
@media (orientation: landscape) {
.hero-image {
height: 60vh;
}
}
/* 組み合わせ:横向きかつ最大高さが500px(スマホ横向きを判別) */
@media (orientation: landscape) and (max-height: 500px) {
.fixed-header {
height: 48px; /* 小さくして画面を有効活用 */
}
.hero {
padding-top: 48px;
}
}
スマートフォンを横向きにすると高さが極端に小さくなるため、固定ヘッダーの高さを減らしたり、ヒーローセクションの余白を詰めたりするのに orientation: landscape と max-height の組み合わせがよく使われます。
macOS・Windows・iOS・Androidなどは「ダークモード」設定を持ち、ユーザーがOSレベルで好みを設定できます。CSSの prefers-color-scheme メディア特性を使うと、その設定を検知してスタイルを切り替えられます。
/* ライトモード(デフォルト) */
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
--color-primary: #d16176;
--color-surface: #f5f5f5;
--color-border: #e0e0e0;
}
/* ダークモード:OSがダークに設定されているとき */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #1a1a1a;
--color-text: #f0f0f0;
--color-primary: #e8889a;
--color-surface: #2c2c2c;
--color-border: #404040;
}
}
/* 実際のスタイル(カスタムプロパティを参照するだけ) */
body {
background-color: var(--color-bg);
color: var(--color-text);
transition: background-color 0.3s ease, color 0.3s ease;
}
.card {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 24px;
}
カスタムプロパティ(CSS変数)と組み合わせるのが定石です。:root に色の変数をまとめておき、prefers-color-scheme: dark のブロックでそれらを上書きするだけで、サイト全体のカラーリングをまとめて切り替えられます。各コンポーネントのスタイルは変数を参照しているだけなので、変更箇所が一箇所に集約されます。
OSの設定に関係なく、ユーザーがボタンでライト・ダークを切り替えられるUIも定番です。その場合は data-theme 属性をHTMLの <html> タグに付けてJavaScriptで操作し、CSSで対応します。
/* OSのデフォルト:ライトモード */
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
}
/* data-theme="dark" が html 要素に付いたとき */
[data-theme="dark"] {
--color-bg: #1a1a1a;
--color-text: #f0f0f0;
}
/* OSがダークのとき、かつ data-theme="light" が指定されていないとき */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-bg: #1a1a1a;
--color-text: #f0f0f0;
}
}
この設計にすると、「OSダークモード」「ユーザーが手動でダーク選択」「ユーザーが手動でライト選択」の3パターンをすべてカバーできます。
これまで解説してきた min-width や max-width の書き方は CSS Media Queries Level 3 の構文です。この書き方でも問題なく動作しますが、「768px以上1199px以下」を書くと (min-width: 768px) and (max-width: 1199px) と冗長になりがちです。
CSS Media Queries Level 4 で導入された range 構文を使うと、不等号記号で条件を直感的に書けます。2026年現在、主要ブラウザのChrome・Firefox・Safari・Edgeすべてで対応済みのため、実務で使い始めて問題ありません。
/* 従来の書き方 */
@media (min-width: 768px) { }
@media (max-width: 767px) { }
@media (min-width: 768px) and (max-width: 1199px) { }
/* ↓ range構文で書き直した版 */
@media (width >= 768px) { }
@media (width < 768px) { }
@media (768px <= width < 1200px) { }
/* heightにも使える */
@media (height >= 600px) {
.hero {
min-height: 100vh;
}
}
/* 実践例:3段階のレスポンシブグリッド */
.grid {
display: grid;
gap: 20px;
}
@media (width < 640px) {
.grid { grid-template-columns: 1fr; }
}
@media (640px <= width < 1024px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (width >= 1024px) {
.grid { grid-template-columns: repeat(3, 1fr); }
}
768px <= width < 1200px のように中間範囲を一行で書けるのが最大のメリットです。数学の不等号と同じ感覚で読めるため、条件の重複や隙間が生じにくく、バグの予防にもなります。新規プロジェクトではrange構文を積極的に採用することをおすすめします。
メディアクエリはビューポート(画面全体の幅)を基準にスタイルを切り替えます。これに対してコンテナクエリは、親要素(コンテナ)の幅を基準にスタイルを切り替えます。2023年以降すべての主要ブラウザで対応が完了し、2026年現在では実務投入が十分可能な技術です。
コンテナクエリが必要になる典型的なシナリオは「同じカードコンポーネントを、サイドバー内(狭い)とメインコンテンツ内(広い)の両方に使いたい」というケースです。メディアクエリだけだと、画面幅を見てしまうため「サイドバーの中でも画面が広ければ大きいレイアウト」という意図しない表示になります。コンテナクエリなら親の幅だけを見るので、配置場所に応じて自動でレイアウトが変わります。
/* 1. 親要素にコンテナとして登録する */
.card-wrapper {
container-type: inline-size; /* 横幅を基準にする */
container-name: card-container; /* 名前は省略可 */
}
/* 2. @container で子要素のスタイルを切り替える */
@container (width >= 400px) {
.card {
display: flex;
gap: 20px;
}
.card__image {
width: 140px;
flex-shrink: 0;
}
}
@container (width < 400px) {
.card {
display: block;
}
.card__image {
width: 100%;
height: 200px;
object-fit: cover;
}
}
/* 名前付きコンテナを指定して適用する場合 */
@container card-container (width >= 500px) {
.card__title {
font-size: 1.4rem;
}
}
container-type: inline-size を指定した要素の子孫が @container の影響を受けます。inline-size はテキストの流れる方向の幅(通常は横幅)を基準にします。縦横両方を基準にしたい場合は size を使いますが、多くのケースでは inline-size で十分です。コンテナクエリはreact・Vueなどのコンポーネントベース開発との相性が非常に良く、再利用性の高いUIを作る際の重要ツールになっています。
メディアクエリを書いてもスマホで効かない原因の第1位は、HTMLの <head> に viewport メタタグが入っていないことです。これがないとスマートフォンはPCサイトを縮小して表示しようとするため、ブレイクポイントに到達せずメディアクエリが一切発動しません。
<!-- <head>に必ず入れる -->
<meta name="viewport" content="width=device-width, initial-scale=1">
デスクトップファーストと同じファイルにモバイルファーストを混在させると、ブレイクポイントの境界で両方のルールが当たってしまう「重複」や、どちらも当たらない「隙間」が起きます。
/* NG:767と768の境界で両方が一瞬当たる可能性 */
@media (max-width: 768px) { }
@media (min-width: 768px) { }
/* OK:境界値をずらして重複を防ぐ */
@media (max-width: 767px) { }
@media (min-width: 768px) { }
/* もっと安全:range構文なら境界が明確 */
@media (width < 768px) { }
@media (width >= 768px) { }
CSSは後に書いたルールが優先されます(詳細度が同じ場合)。モバイルファーストで書く場合は、ベーススタイル → 小さいブレイクポイント → 大きいブレイクポイントの順に並べてください。逆順に書くと、広い画面用のスタイルが狭い画面でも適用されたままになります。
/* OK:モバイルファーストの正しい順序 */
.box { width: 100%; } /* ベース */
@media (min-width: 640px) { .box { width: 50%; } } /* sm */
@media (min-width: 1024px) { .box { width: 33%; } } /* lg */
/* NG:順序が逆になっている */
@media (min-width: 1024px) { .box { width: 33%; } } /* lgが先 */
@media (min-width: 640px) { .box { width: 50%; } } /* smが後に来て上書きしてしまう */
レスポンシブ対応でよく起きるトラブルが、固定幅の画像がコンテナからはみ出すことです。以下をベーススタイルに入れておくと防げます。
/* 全画像のはみ出し防止 */
img {
max-width: 100%;
height: auto;
display: block;
}
/* ビデオにも適用 */
video,
iframe {
max-width: 100%;
}
2つの考え方があります。1つは「ブレイクポイントごとにまとめて書く」方法で、ファイルの末尾に768px用・1024px用とまとめて書きます。もう1つは「コンポーネントごとにその直下に書く」方法で、.nav のスタイルの直後に .nav のメディアクエリを書きます。後者のほうが関連するCSSが近くにあって保守しやすいため、現在は主流です。SassやPostCSSを使う場合もコンポーネントごとにまとめる書き方が一般的です。
メディアクエリの条件値には em を使うことを推奨するエンジニアもいます。理由は、ユーザーがブラウザのフォントサイズを変更したときに em 単位のブレイクポイントが追従するからです。ただし rem はメディアクエリ内では em と同様に機能します。一方で px はもっとも直感的で、デザインツールの数値をそのまま使えます。チームの慣習に合わせるのが現実的で、どれを選んでも大きな差はありません。この記事では読みやすさを優先して px を使っています。
代替ではなく、補完関係にあります。コンテナクエリはコンポーネント単位のレイアウト切り替えに優れていますが、「画面全体の幅でヘッダーの高さを変える」「全体的なカラムレイアウトを切り替える」といったページレベルの制御はメディアクエリが向いています。両者を組み合わせて使うのが2026年現在のベストプラクティスです。
原則として !important の使用は避けるべきです。特にメディアクエリ内で使うと、後でスタイルを上書きしたいときに詰まります。!important が必要に感じる場合は、詳細度の設計が崩れているサインです。セレクタの詳細度を整理するか、カスタムプロパティを使った設計に切り替えることを検討してください。
prefers-reduced-motion は、ユーザーがOSでアニメーションを減らす設定をしているかどうかを検知するメディア特性です。前庭障害を持つユーザーや、過度なアニメーションを好まないユーザーへの配慮として重要です。アクセシビリティの観点から、アニメーションを多用するサイトでは対応することを強くおすすめします。
/* 通常:アニメーションあり */
.button {
transition: transform 0.3s ease, background-color 0.3s ease;
}
.button:hover {
transform: translateY(-2px);
}
/* アニメーション軽減設定のユーザーには動きを止める */
@media (prefers-reduced-motion: reduce) {
.button {
transition: background-color 0.15s ease; /* 色変化は残してもよい */
}
.button:hover {
transform: none;
}
/* すべてのアニメーションを一括で止める場合 */
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
CSSメディアクエリはレスポンシブWebデザインの核心技術です。基本的な @media 構文から始まり、モバイルファーストの考え方、ブレイクポイントの設計、ダークモードやコンテナクエリまで、幅広い表現が1つの技術でカバーできます。この記事のポイントをまとめます。
@media (条件) { スタイル }。and で複数条件を繋げるmin-width を使い、小さい幅から大きい幅へ積み上げるwidth >= 768px)を使うと条件が短く直感的に書ける。主要ブラウザ対応済み@container)は親要素の幅を基準にする新しい仕組み。メディアクエリと使い分けるメディアクエリは「書き方を覚える」よりも「どんな条件でどう変えたいか」という設計思想が大切です。まず基本の min-width パターンを繰り返し使って身体で覚え、慣れてきたらrange構文やコンテナクエリに移行していくステップが最短ルートです。この記事のコード例をそのまま手元でコピペして動かしながら、ぜひ実感してみてください。

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!