10日で覚えるCSSDay 8: レスポンシブデザイン

Day 8: レスポンシブデザイン

今日学ぶこと

  • レスポンシブデザインの原則
  • メディアクエリ
  • モバイルファーストアプローチ
  • レスポンシブな画像とコンテンツ
  • コンテナクエリ

レスポンシブデザインとは

レスポンシブデザインとは、あらゆる画面サイズに適応するWebデザインのアプローチです。

flowchart LR
    subgraph Devices["さまざまなデバイス"]
        Mobile["📱 モバイル<br>〜767px"]
        Tablet["📱 タブレット<br>768〜1023px"]
        Desktop["🖥️ デスクトップ<br>1024px〜"]
    end
    style Mobile fill:#22c55e,color:#fff
    style Tablet fill:#f59e0b,color:#fff
    style Desktop fill:#3b82f6,color:#fff

3つの柱

要素 説明
フルードレイアウト %frで柔軟な幅指定
メディアクエリ 画面サイズに応じてスタイルを変更
フレキシブルなメディア 画像・動画の自動リサイズ

ビューポートメタタグ

レスポンシブデザインの前提条件です。

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

必須: このメタタグがないと、モバイルブラウザはデスクトップ版のページを縮小表示してしまいます。


メディアクエリ

基本構文

@media (max-width: 768px) {
    .container {
        padding: 16px;
    }
}

@media (min-width: 1024px) {
    .container {
        max-width: 1200px;
    }
}

よく使うブレークポイント

/* スマートフォン */
@media (max-width: 767px) { ... }

/* タブレット */
@media (min-width: 768px) and (max-width: 1023px) { ... }

/* デスクトップ */
@media (min-width: 1024px) { ... }

/* 大画面 */
@media (min-width: 1280px) { ... }
ブレークポイント デバイス
640px 小型スマートフォン
768px タブレット
1024px ラップトップ
1280px デスクトップ
1536px 大画面

モバイルファーストアプローチ

小さい画面用のスタイルを先に書き、大きい画面用をmin-widthで追加します。

/* モバイル(デフォルト) */
.grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

/* タブレット以上 */
@media (min-width: 768px) {
    .grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* デスクトップ以上 */
@media (min-width: 1024px) {
    .grid {
        grid-template-columns: repeat(3, 1fr);
        gap: 24px;
    }
}
flowchart LR
    Mobile["📱 モバイル<br>1列"] -->|"768px"| Tablet["📱 タブレット<br>2列"]
    Tablet -->|"1024px"| Desktop["🖥️ デスクトップ<br>3列"]
    style Mobile fill:#22c55e,color:#fff
    style Tablet fill:#f59e0b,color:#fff
    style Desktop fill:#3b82f6,color:#fff

なぜモバイルファースト?: モバイルユーザーは過半数を占めます。必要最小限のスタイルから始め、大画面で拡張するほうが効率的です。


レスポンシブな画像

img {
    max-width: 100%;
    height: auto;
}

レスポンシブな動画

.video-wrapper {
    position: relative;
    padding-bottom: 56.25%;    /* 16:9のアスペクト比 */
    height: 0;
}

.video-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

モダンな方法: aspect-ratioプロパティを使えば、よりシンプルに書けます。

.video-wrapper {
    aspect-ratio: 16 / 9;
    width: 100%;
}

.video-wrapper iframe {
    width: 100%;
    height: 100%;
}

レスポンシブなナビゲーション

/* モバイル: 縦並び */
.nav-links {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* デスクトップ: 横並び */
@media (min-width: 768px) {
    .nav-links {
        flex-direction: row;
        gap: 24px;
    }
}

レスポンシブなタイポグラフィ

clamp() 関数

h1 {
    /* 最小2rem、推奨5vw、最大4rem */
    font-size: clamp(2rem, 5vw, 4rem);
}

p {
    font-size: clamp(1rem, 2.5vw, 1.25rem);
}
引数 説明
最小値 これ以下にはならない
推奨値 ビューポートに応じて変化
最大値 これ以上にはならない

推奨: clamp()を使えば、メディアクエリなしでフォントサイズをスムーズにスケールできます。


コンテナクエリ

画面全体ではなく、親コンテナのサイズに応じてスタイルを変えます。

.card-container {
    container-type: inline-size;
}

@container (min-width: 400px) {
    .card {
        display: flex;
        gap: 16px;
    }
}

@container (min-width: 600px) {
    .card {
        font-size: 1.125rem;
    }
}

注目: コンテナクエリは比較的新しい機能ですが、すべてのモダンブラウザでサポートされています。


実践: レスポンシブなランディングページ

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --color-primary: #3b82f6;
    --max-width: 1200px;
}

body {
    font-family: system-ui, sans-serif;
    line-height: 1.6;
    color: #1e293b;
}

img {
    max-width: 100%;
    height: auto;
}

/* ヘッダー */
.header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    padding: 16px;
}

/* ヒーロー */
.hero {
    text-align: center;
    padding: 48px 16px;
}

.hero h1 {
    font-size: clamp(2rem, 5vw, 3.5rem);
    margin-bottom: 16px;
}

/* カードグリッド */
.cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 32px 16px;
    max-width: var(--max-width);
    margin: 0 auto;
}

/* フッター */
.footer {
    background: #1e293b;
    color: #94a3b8;
    text-align: center;
    padding: 32px 16px;
}

/* タブレット以上 */
@media (min-width: 768px) {
    .header {
        flex-direction: row;
        justify-content: space-between;
        padding: 16px 32px;
    }

    .hero {
        padding: 80px 32px;
    }

    .cards {
        grid-template-columns: repeat(2, 1fr);
        gap: 24px;
        padding: 48px 32px;
    }
}

/* デスクトップ以上 */
@media (min-width: 1024px) {
    .cards {
        grid-template-columns: repeat(3, 1fr);
    }
}

まとめ

概念 説明
レスポンシブデザイン あらゆる画面サイズに適応
メディアクエリ @mediaで条件付きスタイル
モバイルファースト 小→大の順でスタイルを追加
clamp() 最小・推奨・最大のフォントサイズ
コンテナクエリ 親要素のサイズに応じた変化
max-width: 100% 画像のレスポンシブ対応

重要ポイント

  1. ビューポートメタタグは必須
  2. モバイルファーストmin-widthを使う
  3. clamp()メディアクエリなしのレスポンシブを実現
  4. auto-fit + minmax()柔軟なグリッド

練習問題

問題1: 基本

1列(モバイル)→2列(タブレット)→3列(デスクトップ)のレスポンシブグリッドを作成してください。

問題2: 応用

モバイルでハンバーガーメニュー風(縦並び)、デスクトップで横並びのナビゲーションを作成してください。

チャレンジ問題

メディアクエリを一切使わずに、clamp()auto-fitminmax()だけでレスポンシブなページを作成してください。


参考リンク


次回予告: Day 9では「トランジションとアニメーション」について学びます。CSSだけで実現できる動的な表現をマスターしましょう。