Week 08 / Phase 2: CSS(第4週) バイブコーディングの土台 — フロントエンドレッスン

画面幅で変わるCSSを読む
メディアクエリと単位の見方

AIに「スマホ対応にして」と頼むと、@mediaのブロックが増えて返ってきます。そこで起きているのは「ある幅を超えたら別のCSSに切り替わる」というだけのことです。今週は、その切り替えがどちら向きに効いているのかと、AIが置いた数字に根拠があるのかを読めるようにします。

読了時間: 約25分 公開日: 2026年7月30日 前提知識: Week 07 完了

今週のゴール

AIが書いた@mediaを見て、モバイルファーストで書かれているかどうかを判別できる。ブレイクポイントの値が実機の都合に基づくのか、AIが置いた慣習値なのかを疑える。clamp()が出てきたときに何が起きているかを説明できる。「横スクロールが出る」「スマホで文字が小さい」という症状から原因に辿れる。

@media の向きを読む — min-width か max-width か

Week 07 で、repeat(auto-fit, minmax(240px, 1fr)) ならメディアクエリを1行も書かずに列数が変わることを見ました。あれは自動で任せる書き方です。今週扱う @media は、切り替わる幅を自分で指定する書き方です。AIに「スマホ対応にして」と頼んだときに増えるのは、ほぼこちらです。

@media はただの条件分岐

身構える必要はありません。@media は「この条件が真のときだけ、カッコの中のCSSを適用する」というだけの仕組みです。CSSに if 文が付いたと思ってください。

/* 画面幅が 768px 以上のときだけ、この中が適用される */
@media (min-width: 768px) {
    .card-list {
        display: flex;
    }
}

長いCSSを渡されると @media のブロックが何個も並んでいて圧倒されますが、読むべきなのは条件を書いた1行目だけです。中身は今まで通りのCSSで、新しい知識は要りません。

min-width と max-width で「土台」がどちらか分かる

条件に使われるのは、ほぼ min-widthmax-width の2つです。名前が紛らわしいので、ここだけ丁寧に押さえます。

@media (min-width: 768px) { ... }   /* 画面幅が 768px 以上のとき */
@media (max-width: 768px) { ... }   /* 画面幅が 768px 以下のとき */

min-width は「最小でもこの幅があるとき」=それ以上の広い画面。max-width は「最大でもこの幅までのとき」=それ以下の狭い画面です。「min だから小さい画面」と読み間違えるのが定番のつまづきなので、min = 以上、max = 以下と機械的に覚えてしまうのが早いです。

ここから、そのCSSの土台がどちらの画面なのかが読み取れます。

/* ケースA: 土台がスマホ(= モバイルファースト) */
.card-list {
    display: block;              /* ← まずスマホ用。縦に積む */
}
@media (min-width: 768px) {
    .card-list { display: flex; } /* ← 広い画面のときだけ横並びに上書き */
}

/* ケースB: 土台がPC */
.card-list {
    display: flex;               /* ← まずPC用。横並び */
}
@media (max-width: 767px) {
    .card-list { display: block; } /* ← 狭い画面のときだけ縦積みに上書き */
}

@media の外側に書かれているCSSが、そのコードの土台です。@media の中は、条件を満たしたときだけ土台を上書きする追加分にすぎません。だから条件が min-width ばかりなら「土台はスマホ」、max-width ばかりなら「土台はPC」と判別できます。前者の書き方がモバイルファーストと呼ばれるものです。なお自分で書くときにどちらの向きで組み立てるかは、レスポンシブデザイン実践ガイドの「CSSの記述順序」にまとめてあります。今週は読んで判別できるところまでで十分です。

どちらが土台かで、直す場所が変わる

この判別は雑学ではなく、直す場所を決めるために使います。「スマホで見たときだけ崩れている」という状況を考えてください。

「AIに直してもらったのに、スマホの表示が変わらない」という相談は、たいてい土台の側ではなく上書きの側を直しているだけです。どちらの向きで書かれているかを最初に見れば、この空振りは起きません。

両方が混ざっているとき

AIに追加の修正を何度も頼むと、1つのCSSに min-widthmax-width が混在することがあります。前の回答の書き方を引き継がず、そのときの都合で書くためです。

/* 危ないパターン: 768px ちょうどで両方が該当する */
@media (max-width: 768px) {
    .title { font-size: 20px; }
}
@media (min-width: 768px) {
    .title { font-size: 32px; }
}

max-width: 768px は「768px 以下」、min-width: 768px は「768px 以上」なので、ちょうど 768px のときだけ両方が該当します。このとき勝つのはあとに書かれた方で、上の例では 32px になります。ウィンドウ幅がぴったり 768px のときだけ表示が想定と違う、という再現しにくい不具合の正体はこれです。

見つけたときはどちらかの向きに統一するのが本筋です。統一せずに済ませたいなら、境界を max-width: 767.98px のようにずらして重なりを消します。767px にすると、その間の小数の幅がどちらにも該当しない隙間になるので、.98 を使うのが定番です。

@media が全く効かないとき

条件も中身も正しいのに、実機のスマホで @media がまるごと無視されているように見える場合があります。そのときはCSSではなくHTMLの <head> を見てください。

<meta name="viewport" content="width=device-width, initial-scale=1.0">

この1行が無いと、スマホは「自分の画面幅は980pxくらいある」と嘘の申告をしてページ全体を縮小表示します。画面幅が980px扱いなので、max-width: 768px の条件はいつまでも真になりません。この行の意味は Week 04 のメタタグ入門で扱っているので、忘れていたら見直してください。

覚え方: min-width = それ以上の広い画面 = 土台はスマホ。max-width = それ以下の狭い画面 = 土台はPC。土台は必ず @mediaに書いてある。

その数字に根拠はあるか

@media の向きが読めるようになると、次に目に入るのが条件に書かれた数字です。AIはここに 768 / 1024 / 1280 を置いてきます。この数字を疑えるかどうかが、今週いちばん実利のあるところです。

768 / 1024 / 1280 はどこから来た数字か

結論から言うと、よく使われているから使われている数字です。iPadの縦幅が768pxだった、ノートPCが1280pxだった、という由来のある慣習値で、CSSの仕様で決まっているわけでも、あなたのページに合わせて計算されたわけでもありません。AIは学習した大量のコードでこの数字を見ているので、何も指定しなければこれを置きます。

慣習値が悪いという話ではありません。悪いのはその数字が自分のページで妥当かを確かめないまま採用することです。カードが4枚並ぶページと、表が1つあるだけのページで、崩れ始める幅が同じはずがありません。

AIに理由を聞いて、根拠の有無を確かめる

確かめ方は単純で、AIにその数字の理由を聞くだけです。返答は2種類に分かれます。

前者が返ってきたら、そのまま採用しないでください。「デバイスに合わせて決めるのではなく、このページのコンテンツが崩れる幅で決めたいです」と伝えると、AIは中身を見た提案に切り替えます。伝えないと、AIは崩れる幅を知る手段を持ちません。実際の画面を見ていないからです。

崩れる幅を自分で見つける

最終的に判断するのは自分です。ブラウザの開発者ツールで幅を変えながら探します。手順はこれだけです。

  1. ページを開いて F12(Macは Command + Option + I)で開発者ツールを出す
  2. デバイスモード(スマホとタブレットのアイコン)に切り替える。上部に幅の数値が出る
  3. 幅を1280pxあたりから始め、10pxずつ狭めていく
  4. 見た目が「これは読みにくい」に変わった瞬間の数値を記録する
  5. その数値の少し手前を、ブレイクポイントの候補にする

「読みにくいに変わった瞬間」の判断に迷うと思うので、具体的なサインを3つ挙げます。①見出しが不自然な位置で2行になる ②隣り合う要素が重なる・くっつく ③横スクロールバーが出る。どれか1つでも起きたら、そこがあなたのページの限界幅です。慣習値の768pxより手前で起きることも、ずっと先まで平気なことも、どちらもあります。

なお、ここで探しているのは「自分のページの崩れる幅」です。ブレイクポイントを何本置くか、どの順にCSSを書くかといった設計の組み立て方は、レスポンシブデザイン実践ガイドにまとめてあります。今週はAIが置いた数字を検算できる状態までで十分です。

覚え方: ブレイクポイントに正解の数字は無い。自分のコンテンツが崩れる幅が正解。AIが置いた 768 は「よく見る数字」であって、あなたのページを見て決めた数字ではない。

px / % / rem / vw / clamp() の読み分け

AI出力には単位が混ざって出てきます。Week 05 のCSSの単位で一通り扱いましたが、今週必要なのは覚え直しではなく、出てきた単位を見て「画面幅が変わったらこの値はどうなるか」を即答できることです。

見るのは「何を基準に変わるか」だけ

clamp() だけは形が特殊なので、読み方を1つ挙げます。

font-size: clamp(1.8rem, 4vw, 3.2rem);
/* 1つ目の 1.8rem = 最小値。これより小さくならない */
/* 2つ目の 4vw    = 可変値。画面幅に合わせて動く */
/* 3つ目の 3.2rem = 最大値。これより大きくならない */

引数は必ず「最小・可変・最大」の順です。真ん中に画面幅で動く単位(vw)が入っていて、両側が固定値という並びになっていれば、それは「伸縮するが行き過ぎない」という意図です。両端の数字を見れば、どこまで小さくなるか・大きくなるかがそのまま読み取れます。真ん中の 4vw がどこから出てきた数字かは、いま気にしなくて構いません。

AI出力で疑う2つのパターン

単位の意味が分かると、スマホで崩れる予兆が読めるようになります。疑うべきは2つです。

/* パターン1: 幅に px が並んでいる */
.sidebar { width: 320px; }
.main    { width: 880px; }
/* → 合計1200px。375pxの画面では確実にはみ出す */

/* パターン2: font-size に vw が単独で入っている */
.hero-title { font-size: 5vw; }
/* → 375pxの画面では 18.75px、1920pxの画面では 96px。
      下限も上限も無いので、狭い画面で読めなくなる */

パターン1は、AIがPC幅の見た目だけを想定して書いた典型です。幅指定に px が並んでいたら、狭い画面での合計を頭で足してみる癖をつけてください。パターン2は「レスポンシブなタイポグラフィにして」と頼んだときに返ってきやすい形で、clamp() に置き換えれば解決します。

それぞれの単位をどの場面で選ぶか、clamp() の値をどう計算するかは、CSS単位の使い分け完全ガイドに詳しくまとめてあります。今週は読めれば十分で、自分で値を組み立てるのは後からで構いません。

覚え方: 単位を見たら「何が基準か」を1問だけ自分に聞く。pxは基準なし(固定)、%は親、remはルート、vwは画面幅。clamp()は「伸縮するが両端は超えない」。

画像がはみ出す・伸びる

レスポンシブで最初に壊れるのは、たいてい画像です。しかも原因はほぼ1つに決まっているので、見るべき場所も2行だけです。

見るのは2行だけ

img {
    max-width: 100%;   /* ← 親の幅を超えない */
    height: auto;      /* ← 縦横比を保つ */
}

AI出力に画像が含まれていたら、この2行が入っているかを最初に確認してください。入っていなければ、画像は元のファイルの実寸で描画されます。1920px幅の写真は375pxの画面でも1920pxのまま置かれ、親要素を突き破って横スクロールを生みます。

max-width: 100% だけを入れて height: auto を忘れるのもよくある形です。幅は親に収まるようになりますが、高さが元の値のまま残るため、画像が縦に引き伸ばされて潰れます。「なぜか写真だけ縦長に歪んでいる」という症状はこれです。2行はセットで確認してください。

Week 03 の画像を表示する — img タグで、widthheight 属性をHTMLに書きました。あれは読み込み中に枠を確保しておくための指定で、画面幅への追従はCSSのこの2行が担当します。役割が別なので、両方あって構いません。HTMLに width="800" と書いてあるからCSSは不要、とは読まないでください。

srcset が出てきたとき

AI出力に srcset という属性が混ざってくることがあります。

<img src="photo-800.jpg"
     srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
     alt="作業風景">

意味は「同じ写真を複数のサイズで用意しておいて、ブラウザに選ばせる」仕組みです。スマホに1600pxの画像を送る必要は無いので、通信量と表示速度のために使われます。今週はそういう仕組みがあると知っているだけで十分で、書けなくても困りません。

むしろ注意したいのは逆で、AIが srcset を提案してきても、そこに書かれたファイルは存在しないという点です。photo-400.jpg を自分で用意していなければ画像は表示されません。AIはファイルを作れないので、この属性が出てきたら「複数サイズを自分で書き出す作業が付いてくる」と読んでください。

設計の考え方や実装の手順は、それぞれの解説ページにまとめてあります。今週の「読み方」で当たりを付けてから引いてください。

今週の課題

Week 08 課題

Week 07 で作ったカード3枚のレイアウト(Flexbox版とGrid版)を、そのまま使います。今週はこれをスマホ1列 / タブレット2列 / PC3列に切り替わるようにします。ブレイクポイントの数字は慣習値を写さず、自分のカードが崩れる幅を探して決めるのがこの課題の本題です。

必須要件

  1. Week 07 のFlexbox版を土台に使う(Grid版はボーナス課題で扱います)。HTMLは変えず、CSSだけを書き換える
  2. まず@mediaに、スマホ用の状態(カードが縦1列)を書く。ここが土台になる
  3. @mediamin-widthに統一する。max-widthは1つも使わない
  4. ブレイクポイントを2本置く(2列にする幅と、3列にする幅)
  5. その2つの数値を、DevToolsで幅を10pxずつ狭めて崩れる点を探して決める。768 / 1024 をそのまま書かない
  6. 決めた数値の根拠をCSSのコメントに書く(例: /* 2列だとカードが240pxを切るのでここで1列へ */)
  7. カードの見出しか本文のfont-sizeを1箇所 clamp() にする。値はCSS clamp() ジェネレーターで生成する
  8. 幅を375pxにして、横スクロールバーが出ないことを確認する
  9. 画像を1枚入れ、max-width: 100%height: auto付ける前と後の両方を見て、はみ出しが消えるのを確認する
  10. 幅を1280pxから375pxまでゆっくり狭め、3列 → 2列 → 1列と自分が意図した幅で切り替わることを確認する

ボーナス課題

自己チェック項目(提出前に確認)

自己診断テスト

  1. @media (min-width: 768px)はどちらの画面に適用されますか。またそのコードはスマホ基準ですか、PC基準ですか
  2. 「スマホだけ表示を直したい」とき、min-widthで書かれたCSSでは@media中と外のどちらを触りますか
  3. ブレイクポイントの「正しい値」はどう決めますか。AIが置いた768pxをそのまま使ってよいのはどんなときですか?
  4. vwだけでフォントサイズを指定すると何が起きますか。clamp()にすると何が変わりますか?
  5. px / % / rem / vwは、それぞれ何を基準に値が決まりますか?
  6. スマホで横スクロールバーが出たとき、最初に何をしますか。原因の候補を3つ挙げられますか?
  7. 実機のスマホで@mediaがまるごと効いていないように見えるとき、CSSの前に確認するHTMLの1行は何ですか?

答えに詰まった問題があれば、その番号の内容を扱ったセクションに戻ってください。7問すべてを人に説明できる状態になっていれば、AIが出したレスポンシブCSSを渡されても、どこを見ればいいか迷わなくなります。

HTML/CSS土台 完走 — ここまでで身についたこと

Week 01 から8週かけて、AIが出したHTMLとCSSを読んで、崩れている箇所を1つ直せるところまで来ました。全部を自分で書けるようになったわけではありません。それは今も目標ではありません。返ってきたコードのどこを見ればいいか分かる、これがバイブコーディングの土台です。

8週間で身についたのは、具体的にはこの3つです。①構造を読む力(HTMLのどこが何を表しているか) ②見た目の因果を辿る力(なぜこう表示されているかをCSSから説明できる) ③症状から原因に辿る力(崩れを見て確認する場所を絞れる)。この3つは、この先JavaScriptに進んでも同じ形で使い続けます。

HTML/CSS土台 ロードマップ:

  • Week 01〜04(済): HTMLの基本構造・テキスト要素・画像とリンク・セマンティックタグとメタ情報
  • Week 05〜06(済): セレクタ・詳細度・ボックスモデル・display・position
  • Week 07〜08(済・今週): Flexbox・Grid・メディアクエリ・単位
  • この先(Coming): JavaScript、TypeScript、React

次のフェーズはJavaScriptです。ここまでは「表示されているものを読む」話でしたが、JavaScriptからは「動きとデータ」が入ります。AI出力を読むうえでの難易度は一段上がりますが、やることは同じで、最初に見る数行を決めて、そこから辿るだけです。公開までしばらくかかるので、その間はここまでの8週分の課題を、自分のページで作り直してみてください。読めるようになった状態を維持する一番安いやり方は、AIに何かを作らせて読むことです。