Lecture 1Webの仕組み — ブラウザが画面を表示するまで

8:00

Webの仕組み — ブラウザが画面を表示するまで

この講座で作るもの

この講座では、HTML と CSS を使って レスポンシブ対応のポートフォリオサイト を1から作ります。最終回で完成するサイトは、実際にインターネット上に公開できるレベルの品質を目指します。

まず第1回では、「そもそも Web サイトはどうやって表示されるのか」を理解しましょう。仕組みを知ることで、これから書くコードの意味が深く理解できます。

ブラウザとサーバーの会話

Web サイトを見るとき、裏側では ブラウザ(クライアント)サーバー が会話しています。

リクエストとレスポンス

  1. ブラウザのアドレスバーに https://example.com と入力
  2. ブラウザが DNS(電話帳のようなもの)で IP アドレスを調べる
  3. サーバーに HTTP リクエスト(「このページをください」)を送信
  4. サーバーが HTML ファイルを HTTP レスポンス として返す
  5. ブラウザが HTML を解析し、必要な CSS・画像を追加でリクエスト
  6. すべてのファイルが揃ったら画面に表示(レンダリング
[ブラウザ] ---リクエスト---> [サーバー]
[ブラウザ] <--レスポンス---- [サーバー]
           (HTML/CSS/画像)

HTTP/2 では複数のファイルを同時に取得でき、ページの読み込みが高速化されています(RFC 7540, 2015年策定、現在はHTTP/3も普及中)。

Web を構成する3つの言語

Web ページは 3つの言語 の組み合わせで作られています。

言語 役割 例え
HTML 構造(コンテンツ) 家の骨組み
CSS 見た目(デザイン) 壁紙・家具・照明
JavaScript 動き(インタラクション) 照明のスイッチ・自動ドア

この講座では HTML と CSS に集中します。JavaScript は別コース「JavaScript 入門」で学びます。

HTML(HyperText Markup Language)

HTML はテキストに タグ で意味を付ける言語です。

<h1>見出しです</h1>
<p>これは段落です。</p>
  • <h1> は「これは見出し(heading level 1)である」という意味
  • <p> は「これは段落(paragraph)である」という意味

HTML は Tim Berners-Lee が 1991 年に CERN で発明しました。現在の標準は HTML Living Standard(WHATWG が管理)です。

CSS(Cascading Style Sheets)

CSS は HTML の見た目を制御する言語です。

h1 {
  color: #333333;
  font-size: 32px;
}
  • h1 → 「h1 タグに対して」
  • color: #333333; → 「文字色をダークグレーに」
  • font-size: 32px; → 「文字サイズを 32px に」

CSS は Håkon Wium Lie が 1996 年に提案し、現在は CSS3 以降モジュール単位で仕様が策定されています。

開発環境のセットアップ

必要なもの

ツール 推奨 用途
テキストエディタ VS Code(無料) コードを書く
ブラウザ Google Chrome 表示確認 + 開発者ツール

VS Code のインストール

  1. code.visualstudio.com にアクセス
  2. OS に合ったバージョンをダウンロード・インストール
  3. 日本語化: Extensions → 「Japanese Language Pack」をインストール

おすすめの VS Code 拡張機能

拡張機能 用途
Live Server ファイル保存時に自動でブラウザをリロード
Prettier コードの自動フォーマット
Auto Rename Tag 開始タグを変更すると閉じタグも自動変更
HTML CSS Support CSS のクラス名を自動補完

最初のファイルを作る

  1. デスクトップに my-website フォルダを作成
  2. VS Code で「ファイル → フォルダーを開く」→ my-website を選択
  3. 新規ファイル index.html を作成
  4. 以下を入力:
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>はじめてのWebページ</title>
</head>
<body>
  <h1>Hello, World!</h1>
  <p>これは私の最初のWebページです。</p>
</body>
</html>
  1. ファイルを保存(Ctrl+S)
  2. Live Server 拡張で「Go Live」をクリック(または index.html をブラウザにドラッグ&ドロップ)

画面に「Hello, World!」と表示されれば成功です。

Chrome 開発者ツール

Chrome の開発者ツール(DevTools)は Web 開発の必需品です。

開き方

  • F12 キー、または
  • ページ上で右クリック →「検証」

主要なタブ

タブ 用途
Elements HTML の構造と CSS を確認・編集
Console エラーメッセージの確認
Network 読み込まれるファイル一覧と速度
Sources ソースコードの確認

使い方

  1. Elements タブで任意の要素をクリック → 右側に CSS が表示される
  2. CSS の値を直接変更すると、リアルタイムで画面に反映される(リロードすると元に戻る)
  3. 要素の上にマウスを乗せると、ボックスモデル(余白・枠線)が視覚的に表示される

ファイルパスの基本

Web サイトは複数のファイルで構成されます。ファイル同士を参照するための パス の書き方を覚えましょう。

my-website/
├── index.html
├── about.html
├── css/
│   └── style.css
└── images/
    └── photo.jpg

相対パス

現在のファイルからの位置を指定:

<!-- index.html から見て -->
<link rel="stylesheet" href="css/style.css">
<img src="images/photo.jpg" alt="写真">
<a href="about.html">About</a>

絶対パス(外部サイト)

URL を全部書く:

<a href="https://example.com">外部サイト</a>

実践ワーク

  1. VS Code と Chrome をインストールする
  2. my-website フォルダに index.html を作成し、Hello World を表示する
  3. Chrome DevTools(F12)を開き、Elements タブで h1 の文字色を変更してみる

まとめと次回の準備

今回のポイント: - Web はブラウザとサーバーの HTTP 通信で成り立っている - HTML(構造)+ CSS(見た目)+ JavaScript(動き)の3層構造 - VS Code + Live Server + Chrome DevTools が基本の開発環境 - ファイルパスは相対パスと絶対パスの2種類

次回: HTML の主要タグを学びます。見出し、段落、リンク、画像、リストを使って、情報を構造的に表現する方法です。

参考文献: - MDN Web Docs「Getting started with the web」(https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web) - WHATWG「HTML Living Standard」(https://html.spec.whatwg.org/) - Google「Chrome DevTools」(https://developer.chrome.com/docs/devtools/)

Lecture 2はじめてのHTML — 見出し・段落・リンク・画像

12:00

はじめてのHTML — 見出し・段落・リンク・画像

HTMLタグの基本構造

HTML はすべて タグ で構成されます。

<タグ名 属性="値">コンテンツ</タグ名>
  • 開始タグ: <p>
  • 終了タグ: </p>(スラッシュ付き)
  • コンテンツ: タグで囲まれた中身
  • 属性: タグに追加情報を与える
<a href="https://example.com" target="_blank">リンクテキスト</a>

この例では hreftarget が属性、"https://example.com""_blank" が値です。

空要素(自己閉じタグ)

コンテンツを持たないタグもあります:

<img src="photo.jpg" alt="写真の説明">
<br>
<hr>
<input type="text">

これらは終了タグが不要です。

見出しタグ(h1〜h6)

見出しは6段階あります。

<h1>最も重要な見出し(ページタイトル)</h1>
<h2>セクション見出し</h2>
<h3>サブセクション</h3>
<h4>小見出し</h4>
<h5>補足的な見出し</h5>
<h6>最も小さい見出し</h6>

見出しのルール

ルール 理由
<h1> は1ページに1つ SEO とアクセシビリティの基本(WCAG 2.1)
階層を飛ばさない h1→h3 は NG、h1→h2→h3 が正しい
見た目のために使わない 文字を大きくしたいだけなら CSS を使う

Google の検索エンジンは見出しの階層構造を解析してページの内容を理解します。正しい見出し構造は SEO に直結します。

段落と改行

<p>これは段落です。段落の中では、
HTMLソース上の改行は無視されます。
ブラウザ上では1つの段落として表示されます。</p>

<p>新しい段落はpタグで作ります。</p>

<p>どうしても途中で改行したい場合は<br>brタグを使います。</p>

注意: <br> の多用は避けてください。段落を分けるなら <p> タグを使うのが正しい方法です。

リンク(アンカータグ)

<!-- 外部サイトへのリンク -->
<a href="https://example.com">外部サイト</a>

<!-- 同じサイト内のリンク -->
<a href="about.html">Aboutページ</a>

<!-- 新しいタブで開く -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  新しいタブで開く
</a>

<!-- ページ内リンク -->
<a href="#section2">セクション2へ移動</a>
...
<h2 id="section2">セクション2</h2>

<!-- メールリンク -->
<a href="mailto:info@example.com">メールを送る</a>

target="_blank" のセキュリティ

target="_blank" を使う際は rel="noopener noreferrer" を追加してください。これがないと、リンク先のページから元のページを操作できる脆弱性(タブナッピング)が生じる可能性があります。現代のブラウザでは自動で noopener が付与されますが、明示するのがベストプラクティスです。

画像

<img src="images/photo.jpg" alt="東京タワーの夜景" width="800" height="600">
属性 必須 説明
src 画像ファイルのパス
alt 代替テキスト(画像が表示できない場合や、スクリーンリーダーで読み上げ)
width 推奨 幅(px)。指定するとレイアウトのガタつきを防止
height 推奨 高さ(px)。CLS(Cumulative Layout Shift)対策

alt属性の書き方

<!-- 良い例 -->
<img src="chart.png" alt="2024年の月別売上推移グラフ。6月が最高で120万円">

<!-- 悪い例 -->
<img src="chart.png" alt="画像">
<img src="chart.png" alt="">  <!-- 装飾画像でない限りNG -->

<!-- 装飾目的の画像は空のaltでOK -->
<img src="decorative-line.png" alt="">

WCAG 2.1(Web Content Accessibility Guidelines)では、すべての非テキストコンテンツに代替テキストの提供を求めています。

リスト

順序なしリスト(箇条書き)

<ul>
  <li>HTML</li>
  <li>CSS</li>
  <li>JavaScript</li>
</ul>

順序ありリスト(番号付き)

<ol>
  <li>企画</li>
  <li>設計</li>
  <li>開発</li>
  <li>テスト</li>
</ol>

入れ子のリスト

<ul>
  <li>フロントエンド
    <ul>
      <li>HTML</li>
      <li>CSS</li>
      <li>JavaScript</li>
    </ul>
  </li>
  <li>バックエンド
    <ul>
      <li>Python</li>
      <li>Node.js</li>
    </ul>
  </li>
</ul>

説明リスト

<dl>
  <dt>HTML</dt>
  <dd>Webページの構造を定義する言語</dd>
  <dt>CSS</dt>
  <dd>Webページの見た目を装飾する言語</dd>
</dl>

テーブル(表)

<table>
  <thead>
    <tr>
      <th>名前</th>
      <th>役職</th>
      <th>メール</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>田中太郎</td>
      <td>エンジニア</td>
      <td>tanaka@example.com</td>
    </tr>
    <tr>
      <td>鈴木花子</td>
      <td>デザイナー</td>
      <td>suzuki@example.com</td>
    </tr>
  </tbody>
</table>
タグ 意味
<table> 表全体
<thead> ヘッダー行グループ
<tbody> データ行グループ
<tr> 行(table row)
<th> 見出しセル(太字・中央揃え)
<td> データセル

コメント

<!-- これはコメントです。ブラウザには表示されません -->

<!--
  複数行のコメントも
  このように書けます
-->

コメントはブラウザに表示されませんが、HTML ソースには残ります。パスワードなどの機密情報は絶対にコメントに書かないでください。

HTMLの文書構造テンプレート

ここまでの知識を組み合わせた基本テンプレートです:

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ページタイトル</title>
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <h1>メインタイトル</h1>

  <h2>セクション1</h2>
  <p>段落テキスト。<a href="https://example.com">リンク</a>も含められます。</p>
  <img src="images/photo.jpg" alt="写真の説明" width="800" height="600">

  <h2>セクション2</h2>
  <ul>
    <li>項目1</li>
    <li>項目2</li>
    <li>項目3</li>
  </ul>

  <h2>データ</h2>
  <table>
    <thead>
      <tr><th>項目</th><th></th></tr>
    </thead>
    <tbody>
      <tr><td>売上</td><td>100万円</td></tr>
    </tbody>
  </table>
</body>
</html>

実践ワーク

my-website/index.html を以下の内容で作り直してください:

  1. 自分の名前を <h1>
  2. 自己紹介を <p> で3段落
  3. 趣味を <ul> でリスト化
  4. 好きな Web サイトへのリンクを3つ
  5. 任意の画像を1枚表示(フリー素材サイト Unsplash 等から取得)
  6. スキルを <table> で表にまとめる

まとめと次回の準備

今回のポイント: - HTML はタグでテキストに意味を付ける言語 - <h1><h6> は見出しの階層構造。SEO とアクセシビリティに重要 - <a> リンク、<img> 画像、<ul>/<ol> リスト、<table> 表が基本パーツ - alt 属性は必ず書く(WCAG 2.1 準拠)

次回: セマンティック HTML(header, nav, main, section, footer)とフォーム(input, select, textarea)を学びます。意味のある構造で、検索エンジンにも人間にも伝わるページを作ります。

参考文献: - MDN Web Docs「HTML の基本」(https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/HTML_basics) - W3C「WCAG 2.1」(https://www.w3.org/TR/WCAG21/) - Google「Search Central — 見出しタグの使い方」(https://developers.google.com/search/docs/fundamentals/seo-starter-guide)

Lecture 3HTMLの構造化 — セマンティックタグとフォーム

12:00

HTMLの構造化 — セマンティックタグとフォーム

セマンティックHTMLとは

HTML5 で導入された セマンティックタグ は、コンテンツの「意味」を明確にするタグです。<div> はただの箱ですが、<header> は「ここはヘッダーだ」とブラウザや検索エンジンに伝えます。

divで書いた場合(非セマンティック)

<div id="header">
  <div id="nav">...</div>
</div>
<div id="main">
  <div class="article">...</div>
  <div id="sidebar">...</div>
</div>
<div id="footer">...</div>

セマンティックタグで書いた場合

<header>
  <nav>...</nav>
</header>
<main>
  <article>...</article>
  <aside>...</aside>
</main>
<footer>...</footer>

どちらも見た目は同じにできますが、後者は 検索エンジンスクリーンリーダー将来の自分 にとって読みやすいコードです。

主要なセマンティックタグ

タグ 意味 使い方
<header> ページまたはセクションのヘッダー サイトロゴ、ナビゲーション
<nav> ナビゲーション メインメニュー、パンくずリスト
<main> ページのメインコンテンツ(1ページに1つ) 記事本文、商品一覧
<article> 独立したコンテンツの塊 ブログ記事、ニュース記事
<section> テーマでグループ化されたコンテンツ 「サービス紹介」セクション
<aside> メインコンテンツと間接的に関連する補足 サイドバー、関連記事
<footer> ページまたはセクションのフッター 著作権表示、リンク集
<figure> + <figcaption> 図版とそのキャプション 画像 + 説明文

典型的なページ構造

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CLAN サンプルサイト</title>
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <header>
    <h1>CLAN</h1>
    <nav>
      <ul>
        <li><a href="index.html">ホーム</a></li>
        <li><a href="about.html">About</a></li>
        <li><a href="contact.html">お問い合わせ</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <section>
      <h2>サービス紹介</h2>
      <article>
        <h3>Webサイト制作</h3>
        <p>レスポンシブ対応のモダンなWebサイトを制作します。</p>
      </article>
      <article>
        <h3>SEOコンサルティング</h3>
        <p>検索エンジン最適化で集客をサポートします。</p>
      </article>
    </section>

    <aside>
      <h2>お知らせ</h2>
      <ul>
        <li>2025/01/15 — サイトをリニューアルしました</li>
        <li>2025/01/01 — 新年のご挨拶</li>
      </ul>
    </aside>
  </main>

  <footer>
    <p>&copy; 2025 CLAN. All rights reserved.</p>
  </footer>
</body>
</html>

figure と figcaption

画像にキャプション(説明文)を付けたいときに使います。

<figure>
  <img src="images/tokyo-tower.jpg" alt="東京タワーの夜景" width="800" height="600">
  <figcaption>東京タワー(2024年12月撮影)</figcaption>
</figure>

<figure> は画像だけでなく、コードブロック、引用、表など「本文から参照される独立した要素」に使えます。

フォーム

Web サイトの「お問い合わせ」「ログイン」「検索」— これらはすべて フォーム で実現します。

基本構造

<form action="/submit" method="POST">
  <!-- フォーム要素をここに配置 -->
  <button type="submit">送信</button>
</form>
属性 説明
action データの送信先URL
method GET(URLパラメータ)または POST(本文に含める)

入力フィールドの種類

<form action="/contact" method="POST">
  <!-- テキスト入力 -->
  <label for="name">お名前</label>
  <input type="text" id="name" name="name" required placeholder="山田太郎">

  <!-- メールアドレス -->
  <label for="email">メールアドレス</label>
  <input type="email" id="email" name="email" required placeholder="example@mail.com">

  <!-- 電話番号 -->
  <label for="tel">電話番号</label>
  <input type="tel" id="tel" name="tel" placeholder="090-1234-5678">

  <!-- パスワード -->
  <label for="password">パスワード</label>
  <input type="password" id="password" name="password" minlength="8">

  <!-- 数値 -->
  <label for="age">年齢</label>
  <input type="number" id="age" name="age" min="0" max="120">

  <!-- 日付 -->
  <label for="date">希望日</label>
  <input type="date" id="date" name="date">

  <!-- ラジオボタン -->
  <fieldset>
    <legend>ご希望のプラン</legend>
    <label><input type="radio" name="plan" value="basic"> ベーシック</label>
    <label><input type="radio" name="plan" value="pro"> プロ</label>
    <label><input type="radio" name="plan" value="enterprise"> エンタープライズ</label>
  </fieldset>

  <!-- チェックボックス -->
  <label>
    <input type="checkbox" name="agree" required>
    利用規約に同意する
  </label>

  <!-- セレクトボックス -->
  <label for="category">カテゴリ</label>
  <select id="category" name="category">
    <option value="">選択してください</option>
    <option value="inquiry">お問い合わせ</option>
    <option value="request">資料請求</option>
    <option value="other">その他</option>
  </select>

  <!-- テキストエリア -->
  <label for="message">メッセージ</label>
  <textarea id="message" name="message" rows="5" placeholder="お気軽にお問い合わせください"></textarea>

  <button type="submit">送信</button>
</form>

label の重要性

<label> タグの for 属性と <input>id を一致させることで:

  1. ラベルをクリックすると入力欄にフォーカスが移る(操作性向上)
  2. スクリーンリーダーが入力欄の目的を読み上げる(アクセシビリティ)

<label> なしの <input> は絶対に避けてください。 WCAG 2.1 の達成基準 1.3.1(情報及び関係性)に違反します。

バリデーション属性

<input type="email" required>              <!-- 必須 + メール形式チェック -->
<input type="text" minlength="3" maxlength="50">  <!-- 文字数制限 -->
<input type="number" min="1" max="100">     <!-- 数値範囲 -->
<input type="text" pattern="[0-9]{3}-[0-9]{4}">   <!-- 正規表現パターン -->

HTML のバリデーションはユーザーの利便性のためのもので、セキュリティの保証にはなりません。サーバー側でのバリデーションも必ず実装してください。

<head> 内に配置するメタ情報はページの設定を制御します。

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="ページの説明文(120文字以内推奨)">
  <meta name="robots" content="index, follow">
  <title>ページタイトル(30文字以内推奨)</title>
  <link rel="stylesheet" href="css/style.css">
  <link rel="icon" href="favicon.ico">
</head>
タグ 用途
charset="UTF-8" 文字コード指定(日本語を正しく表示)
viewport スマートフォンでの表示サイズ制御
description Google 検索結果に表示される説明文
title ブラウザのタブに表示されるタイトル
link rel="stylesheet" CSS ファイルの読み込み
link rel="icon" ファビコン(タブのアイコン)

実践ワーク

前回作った index.html を以下のようにリニューアルしてください:

  1. <header>, <nav>, <main>, <footer> でページを構造化
  2. ナビゲーションに3つのリンク(ホーム、About、お問い合わせ)
  3. <section> で2つのセクション(自己紹介 + スキル)
  4. contact.html を新規作成し、お問い合わせフォーム(名前、メール、カテゴリ選択、メッセージ)を設置

まとめと次回の準備

今回のポイント: - セマンティックタグ(header, nav, main, article, aside, footer)でページの意味を明確に - <div> は他に適切なタグがない場合のみ使う - フォームでは <label><input> を必ずセットで使う - head 内のメタ情報(description, viewport)は SEO とレスポンシブの基本

次回: いよいよ CSS です。セレクタ、プロパティ、カスケード(優先順位)を学び、HTML に色とデザインを加えます。

参考文献: - MDN Web Docs「HTML要素リファレンス」(https://developer.mozilla.org/ja/docs/Web/HTML/Element) - W3C「HTML5 セマンティック要素」(https://www.w3.org/TR/html52/sections.html) - Google「検索セントラル — 構造化データ」(https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data)

Lecture 4CSSの基本 — セレクタ・プロパティ・カスケード

12:00

CSSの基本 — セレクタ・プロパティ・カスケード

CSSの3つの記述方法

1. 外部ファイル(推奨)

<!-- index.html -->
<link rel="stylesheet" href="css/style.css">
/* css/style.css */
h1 {
  color: #333;
}

2. styleタグ(head内)

<head>
  <style>
    h1 { color: #333; }
  </style>
</head>

3. インラインスタイル(非推奨)

<h1 style="color: #333;">タイトル</h1>

外部ファイルが推奨される理由: HTML(構造)と CSS(見た目)を分離できる、複数ページで同じ CSS を共有できる、ブラウザがキャッシュして高速化できる。

セレクタの基本

CSS は「何を」「どう変えるか」を指定する言語です。

セレクタ {
  プロパティ: ;
  プロパティ: ;
}

要素セレクタ

/* すべてのpタグに適用 */
p {
  color: #333;
  line-height: 1.8;
}

/* すべてのh2タグに適用 */
h2 {
  font-size: 24px;
  border-bottom: 2px solid #007bff;
}

クラスセレクタ(最も使用頻度が高い)

<p class="highlight">強調したいテキスト</p>
<p class="highlight large">複数のクラスも指定可能</p>
.highlight {
  background-color: #fff3cd;
  padding: 8px;
}

.large {
  font-size: 20px;
}

IDセレクタ

<div id="header">ヘッダー</div>
#header {
  background-color: #f8f9fa;
}

ID はページ内で一意でなければなりません。CSS ではクラスセレクタの使用が推奨されます(ID は詳細度が高すぎて上書きしにくいため)。

属性セレクタ

/* type="email" のinputだけ */
input[type="email"] {
  border-color: #007bff;
}

/* target="_blank" のリンクにアイコンを追加 */
a[target="_blank"]::after {
  content: " ↗";
}

結合子(コンビネータ)

子孫セレクタ(スペース)

/* nav の中にある a タグすべて */
nav a {
  text-decoration: none;
  color: #007bff;
}

子セレクタ(>)

/* ul の直接の子要素の li のみ(孫は含まない) */
ul > li {
  list-style-type: disc;
}

隣接兄弟セレクタ(+)

/* h2 の直後の p だけ */
h2 + p {
  font-size: 18px;
  color: #666;
}

疑似クラスと疑似要素

疑似クラス

/* マウスを乗せたとき */
a:hover {
  color: #0056b3;
  text-decoration: underline;
}

/* フォーカス中の入力欄 */
input:focus {
  outline: 2px solid #007bff;
  border-color: #007bff;
}

/* 最初の子要素 */
li:first-child {
  font-weight: bold;
}

/* 奇数番目の行 */
tr:nth-child(odd) {
  background-color: #f8f9fa;
}

疑似要素

/* 要素の前にコンテンツを追加 */
.required::before {
  content: "※ ";
  color: red;
}

/* 最初の1文字だけ大きく */
p::first-letter {
  font-size: 2em;
  font-weight: bold;
}

カスケード(優先順位)

CSS が「Cascading」Style Sheets と呼ばれる理由は、複数のルールが競合したときに 優先順位(詳細度) で勝敗が決まるからです。

詳細度(Specificity)

セレクタ 詳細度
要素セレクタ 0-0-1 p, h1, div
クラスセレクタ 0-1-0 .highlight, .btn
IDセレクタ 1-0-0 #header, #main
インラインスタイル 最強 style="..."
p { color: blue; }           /* 0-0-1 */
.text { color: green; }      /* 0-1-0 → こちらが勝つ */
#intro { color: red; }       /* 1-0-0 → さらに強い */

同じ詳細度なら後に書いたルールが勝つ

p { color: blue; }
p { color: red; }  /* こちらが適用される */

!important(最後の手段)

p {
  color: red !important;  /* 他のすべてのルールに勝つ */
}

!important は原則使わないでください。 使うと他の CSS で上書きできなくなり、保守性が著しく低下します。どうしても必要な場合のみ限定的に使用してください。

よく使うプロパティ一覧

テキスト関連

.text-example {
  color: #333;                  /* 文字色 */
  font-size: 16px;              /* 文字サイズ */
  font-weight: bold;            /* 太さ: normal, bold, 100-900 */
  font-family: "Noto Sans JP", sans-serif;  /* フォント */
  line-height: 1.8;             /* 行間(文字サイズの1.8倍) */
  text-align: center;           /* 揃え: left, center, right, justify */
  text-decoration: none;        /* 下線の制御 */
  letter-spacing: 0.05em;       /* 文字間隔 */
}

背景

.bg-example {
  background-color: #f8f9fa;
  background-image: url("images/bg.jpg");
  background-size: cover;           /* 要素全体を覆う */
  background-position: center;      /* 中央に配置 */
  background-repeat: no-repeat;     /* 繰り返さない */
}

サイズ

.size-example {
  width: 100%;           /* 親要素の幅いっぱい */
  max-width: 1200px;     /* 最大幅の制限 */
  height: auto;          /* 自動計算 */
  min-height: 100vh;     /* ビューポート高さの100% */
}

表示・非表示

.hidden { display: none; }              /* 完全に非表示(スペースも消える) */
.invisible { visibility: hidden; }       /* 見えないがスペースは残る */
.transparent { opacity: 0; }            /* 透明だがスペースは残る */

CSSのリセット

ブラウザにはデフォルトの CSS が設定されています(例: h1 は大きく太字、body に 8px のマージン)。これを統一するのが CSS リセット です。

最小限のリセット

/* css/style.css の冒頭に */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  line-height: 1.8;
  color: #333;
}

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

box-sizing: border-box は、padding と border を width に含める設定です。これがないと、width: 100% + padding: 20px でコンテンツが親要素からはみ出します。現代の CSS では事実上必須の設定です。

実践ワーク

  1. css/style.css を作成し、index.html から読み込む
  2. CSS リセットを冒頭に記述
  3. 以下のスタイルを適用:
  4. ヘッダーに背景色を設定、ナビリンクの下線を消す
  5. 見出し(h2)に下線を付ける
  6. テーブルに縞模様(:nth-child(odd))を付ける
  7. ボタンに :hover でのスタイル変化を設定

まとめと次回の準備

今回のポイント: - CSS は外部ファイルに書く(HTML と分離) - セレクタ: 要素、クラス(.)、ID(#)。クラスの使用が推奨 - カスケード: 詳細度で優先順位が決まる。!important は避ける - box-sizing: border-box と CSS リセットは現代開発の必須設定

次回: ボックスモデル(margin, padding, border)を深掘りし、余白を使ったレイアウト設計を学びます。

参考文献: - MDN Web Docs「CSS の第一歩」(https://developer.mozilla.org/ja/docs/Learn/CSS/First_steps) - MDN Web Docs「詳細度」(https://developer.mozilla.org/ja/docs/Web/CSS/Specificity) - Josh Comeau「My Custom CSS Reset」(https://www.joshwcomeau.com/css/custom-css-reset/)

Lecture 5ボックスモデルと余白設計 — margin, padding, border

10:00

ボックスモデルと余白設計 — margin, padding, border

すべては「箱」でできている

HTML のすべての要素は ボックス(箱)としてレンダリングされます。Chrome DevTools の Elements タブで要素を選択すると、このボックスが色分けで表示されます。

ボックスモデルの4層構造

内側から外側に向かって:

┌──────────────── margin(外側の余白)─────────────────┐
│ ┌──────────────── border(枠線)────────────────────┐ │
│ │ ┌──────────────── padding(内側の余白)──────────┐ │ │
│ │ │                                                │ │ │
│ │ │              content(コンテンツ)              │ │ │
│ │ │                                                │ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
プロパティ 役割
content width, height テキスト・画像が表示される領域
padding padding コンテンツと枠線の間の余白(背景色が適用される)
border border 枠線
margin margin 要素の外側の余白(透明、背景色は適用されない)

box-sizing の違い

content-box(デフォルト、直感に反する)

.box-content {
  box-sizing: content-box;  /* デフォルト */
  width: 300px;
  padding: 20px;
  border: 1px solid #000;
}
/* 実際の幅 = 300 + 20*2 + 1*2 = 342px */

border-box(推奨)

.box-border {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 1px solid #000;
}
/* 実際の幅 = 300px(paddingとborderが含まれる) */

border-box を全要素に適用する のが現代の標準です。前回の CSS リセットで設定済みです。

padding(内側の余白)

一括指定

/* 上下左右すべて 20px */
padding: 20px;

/* 上下 10px、左右 20px */
padding: 10px 20px;

/* 上 10px、左右 20px、下 30px */
padding: 10px 20px 30px;

/* 上 10px、右 20px、下 30px、左 40px(時計回り) */
padding: 10px 20px 30px 40px;

個別指定

padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;

padding の使いどころ

/* ボタンの内側余白 */
.btn {
  padding: 12px 24px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

/* カード内の余白 */
.card {
  padding: 24px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

margin(外側の余白)

一括指定(padding と同じ書式)

margin: 20px;           /* 上下左右 */
margin: 10px 20px;      /* 上下、左右 */
margin: 0 auto;         /* 上下0、左右autoで中央寄せ */

中央寄せ(頻出パターン)

ブロック要素を水平中央に配置する最も一般的な方法:

.container {
  max-width: 1200px;
  margin: 0 auto;      /* 上下0、左右auto = 中央 */
  padding: 0 20px;     /* 左右に余白を確保 */
}

マージンの相殺(Margin Collapsing)

隣接する上下のマージンは 大きい方に統合 されます。これを「マージンの相殺」と呼びます。

.section-a { margin-bottom: 30px; }
.section-b { margin-top: 20px; }
/* 2つの間の余白は 30px + 20px = 50px ではなく、30px */

マージンの相殺が起きる条件: - 隣接する兄弟要素の上下マージン - 親要素と最初/最後の子要素の上下マージン - 空のブロック要素の上下マージン

回避方法: padding を使う、border を設定する、overflow: hidden を使う。

border(枠線)

/* 一括指定 */
border: 1px solid #ddd;

/* 個別指定 */
border-width: 1px;
border-style: solid;    /* solid, dashed, dotted, double, none */
border-color: #ddd;

/* 特定の辺だけ */
border-bottom: 2px solid #007bff;
border-left: 4px solid #28a745;

/* 角丸 */
border-radius: 8px;     /* すべての角 */
border-radius: 50%;     /* 正方形に適用すると円になる */
border-radius: 8px 0 0 8px;  /* 左上・右上・右下・左下 */

display プロパティ

HTML 要素には ブロック要素インライン要素 の2種類があります。

種類 特徴 代表的なタグ
ブロック 幅いっぱいに広がる、前後に改行 div, p, h1h6, section
インライン コンテンツ分の幅、改行なし span, a, strong, em

display で切り替え

/* インライン要素をブロックにする */
a { display: block; }

/* ブロック要素をインラインにする */
li { display: inline; }

/* 両方の性質を持つ inline-block */
.badge {
  display: inline-block;
  padding: 4px 8px;
  background-color: #007bff;
  color: white;
  border-radius: 4px;
}

inline-block はインラインのように横に並びながら、ブロックのように width/height/padding/margin を設定できます。

余白設計の原則

8pxグリッドシステム

多くのモダンデザインシステムでは 8px の倍数 で余白を設計します(Google Material Design が採用)。

:root {
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
}

h2 { margin-bottom: var(--space-md); }
.section { padding: var(--space-2xl) 0; }
.card { padding: var(--space-lg); }

CSS カスタムプロパティ(変数)

:root {
  --color-primary: #007bff;
  --color-text: #333;
  --font-base: 16px;
}

.btn {
  background-color: var(--color-primary);
  color: white;
  font-size: var(--font-base);
}

:root はドキュメント全体を指すセレクタです。ここで定義した変数はどこからでも参照できます。色やサイズを一箇所で管理できるため、変更時に全ファイルを書き換える必要がありません。

実践ワーク

  1. ヘッダーに paddingbackground-color を設定
  2. メインコンテンツに max-width: 960px; margin: 0 auto; で中央寄せ
  3. セクション間に margin-bottom で余白を設定
  4. .card クラスを作り、padding, border-radius, box-shadow でカードデザインを実装
  5. .btn クラスを作り、ボタンスタイルを実装(:hover で色を変える)

まとめと次回の準備

今回のポイント: - ボックスモデル: content → padding → border → margin の4層構造 - box-sizing: border-box で直感的なサイズ計算に - margin: 0 auto でブロック要素を中央寄せ - マージンの相殺に注意(上下マージンは統合される) - 8px グリッドと CSS 変数で一貫した余白設計

次回: カラーとタイポグラフィ。色の指定方法(hex, rgb, hsl)、フォントの選び方、読みやすいテキストデザインの原則を学びます。

参考文献: - MDN Web Docs「ボックスモデル」(https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/The_box_model) - Google Material Design「Spacing」(https://m3.material.io/foundations/layout/understanding-layout/spacing) - CSS-Tricks「A Complete Guide to CSS Custom Properties」(https://css-tricks.com/a-complete-guide-to-custom-properties/)

Lecture 6カラーとタイポグラフィ — 読みやすいデザインの原則

10:00

カラーとタイポグラフィ — 読みやすいデザインの原則

色の指定方法

CSS には複数の色の指定方法があります。

HEX(16進数)

color: #333333;        /* ダークグレー */
color: #333;           /* 短縮形(各桁が同じ場合) */
color: #007bff;        /* 青 */
color: #ff6b6b;        /* 赤 */

6桁の16進数で、先頭2桁が赤(R)、中央2桁が緑(G)、末尾2桁が青(B)。00 が最小(暗い)、ff が最大(明るい)。

RGB / RGBA

color: rgb(51, 51, 51);              /* ダークグレー */
color: rgb(0, 123, 255);             /* 青 */
color: rgba(0, 123, 255, 0.5);       /* 青、50%透明 */

RGBA の4番目の値(アルファ)は 0(完全透明)〜 1(完全不透明)。半透明のオーバーレイやシャドウに便利です。

HSL / HSLA

color: hsl(210, 100%, 50%);          /* 青 */
color: hsl(210, 100%, 40%);          /* 暗い青(明度を下げた) */
color: hsl(210, 50%, 50%);           /* くすんだ青(彩度を下げた) */
color: hsla(210, 100%, 50%, 0.5);    /* 半透明の青 */
  • H(色相): 0〜360(色相環の角度。0=赤、120=緑、240=青)
  • S(彩度): 0%〜100%(0%=灰色、100%=鮮やか)
  • L(明度): 0%〜100%(0%=黒、50%=純色、100%=白)

HSL はカラーパレット設計に最適です。 色相を固定して彩度・明度を変えるだけで、統一感のある配色が作れます。

配色の基本原則

60-30-10 ルール

比率 用途
60% ベースカラー(背景) 白、ライトグレー
30% サブカラー(セクション背景、カード) ダークグレー、ライトブルー
10% アクセントカラー(ボタン、リンク、CTA) 鮮やかな青、オレンジ

実装例

:root {
  /* 60% ベース */
  --color-bg: #ffffff;
  --color-bg-alt: #f8f9fa;

  /* 30% サブ */
  --color-text: #333333;
  --color-text-light: #6c757d;

  /* 10% アクセント */
  --color-primary: #007bff;
  --color-primary-dark: #0056b3;
  --color-accent: #ff6b35;
}

body {
  background-color: var(--color-bg);
  color: var(--color-text);
}

.section-alt {
  background-color: var(--color-bg-alt);
}

.btn-primary {
  background-color: var(--color-primary);
  color: white;
}

.btn-primary:hover {
  background-color: var(--color-primary-dark);
}

コントラスト比

WCAG 2.1 では、テキストと背景のコントラスト比に最低基準があります:

レベル 通常テキスト 大きなテキスト(18px以上の太字 or 24px以上)
AA(最低限) 4.5:1 以上 3:1 以上
AAA(推奨) 7:1 以上 4.5:1 以上
/* NG: コントラスト不足 */
.bad { color: #999; background: #fff; }   /* 2.85:1 */

/* OK: AA基準クリア */
.good { color: #595959; background: #fff; } /* 7:1 */

コントラスト比は WebAIM の Contrast Checker(https://webaim.org/resources/contrastchecker/)で確認できます。Chrome DevTools でも要素を選択すると表示されます。

タイポグラフィ

フォントの指定

body {
  font-family:
    "Noto Sans JP",        /* 第1候補: Googleフォント */
    "Hiragino Kaku Gothic ProN",  /* 第2候補: macOS標準 */
    "Meiryo",              /* 第3候補: Windows標準 */
    sans-serif;            /* 総称ファミリー(フォールバック) */
}

Google Fonts の使い方

<!-- head内に追加 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
body {
  font-family: "Noto Sans JP", sans-serif;
}

display=swap はフォント読み込み中にシステムフォントで表示し、ロード完了後に切り替える設定です。FOIT(Flash of Invisible Text)を防ぎます。

文字サイズの設計

相対単位 rem を使うと、ユーザーのブラウザ設定(文字サイズ変更)を尊重できます。

html {
  font-size: 16px;   /* 1rem = 16px がデフォルト */
}

body {
  font-size: 1rem;      /* 16px */
  line-height: 1.8;     /* 行間 = 16 × 1.8 = 28.8px */
}

h1 { font-size: 2rem; }      /* 32px */
h2 { font-size: 1.5rem; }    /* 24px */
h3 { font-size: 1.25rem; }   /* 20px */
small { font-size: 0.875rem; } /* 14px */

px, em, rem の違い

単位 基準
px 絶対値 16px
em 親要素の font-size 1.5em(親が 16px なら 24px)
rem ルート(html)の font-size 1.5rem(常に 24px)

rem の使用を推奨します。 em は入れ子で累積するため、意図しないサイズになることがあります。

読みやすさの3原則

1. 行間(line-height)

/* 日本語テキスト: 1.7〜2.0 が読みやすい */
p { line-height: 1.8; }

/* 見出し: やや狭め */
h1, h2, h3 { line-height: 1.3; }

英語より日本語のほうが文字の密度が高いため、行間は広めが適切です。

2. 行の長さ(最大文字数)

p {
  max-width: 40em;  /* 約40文字分(日本語) */
}

1行が長すぎると目が追いにくくなります。英語は 60〜75 文字、日本語は 35〜45 文字が読みやすいとされています(Robert Bringhurst『The Elements of Typographic Style』)。

3. 文字間隔(letter-spacing)

/* 日本語はわずかに広げると読みやすい */
body { letter-spacing: 0.05em; }

/* 見出しは通常〜やや詰め */
h1 { letter-spacing: 0; }

テキストの装飾

/* 太字 */
strong, .bold { font-weight: 700; }

/* 斜体(日本語ではあまり使わない) */
em { font-style: italic; }

/* 下線 */
.underline { text-decoration: underline; }

/* 打ち消し線 */
.deleted { text-decoration: line-through; color: #999; }

/* 大文字変換(英語用) */
.uppercase { text-transform: uppercase; }

/* テキストの影 */
.shadow { text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); }

実践ワーク

  1. CSS 変数でカラーパレットを定義(base, sub, accent の3色)
  2. Google Fonts「Noto Sans JP」を読み込み、body に適用
  3. h1h3pfont-sizerem で設定
  4. line-height1.8 に設定して行間を確保
  5. WebAIM Contrast Checker でテキスト色と背景色のコントラスト比を確認

まとめと次回の準備

今回のポイント: - 色指定: HEX, RGB, HSL。配色設計には HSL が便利 - 60-30-10 ルールで統一感のある配色 - コントラスト比 4.5:1 以上(WCAG 2.1 AA 基準) - フォントサイズは rem で指定、行間は 1.7〜2.0 - CSS 変数で色・サイズを一元管理

次回: いよいよ Flexbox。横並びレイアウトの決定版で、ナビゲーション、カードレイアウト、フッターなどを自在に配置します。

参考文献: - W3C「WCAG 2.1 — コントラスト」(https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html) - Google Fonts(https://fonts.google.com/) - Robert Bringhurst『The Elements of Typographic Style』Version 4.0(Hartley & Marks, 2012)

Lecture 7Flexbox — 横並びレイアウトの決定版

12:00

Flexbox — 横並びレイアウトの決定版

なぜ Flexbox なのか

CSS レイアウトの歴史:

時代 手法 問題
1990年代 <table> レイアウト セマンティックでない、複雑
2000年代 float + clearfix バグが多い、直感的でない
2010年代〜 Flexbox 直感的、柔軟
2017年〜 CSS Grid 2次元レイアウトに最適

Flexbox は 1次元レイアウト(横1列 or 縦1列)に最適なシステムです。Can I Use(https://caniuse.com/flexbox)によると、現代ブラウザの 99%以上が対応しています。

Flexbox の基本

親要素に display: flex を指定するだけ

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
.container {
  display: flex;
}

.item {
  padding: 20px;
  background-color: #007bff;
  color: white;
  margin: 4px;
}

これだけで子要素が 横並び になります。floatinline-block も不要です。

用語

  • Flex コンテナ: display: flex を設定した親要素
  • Flex アイテム: コンテナの直接の子要素
  • 主軸(Main Axis): アイテムが並ぶ方向(デフォルトは横)
  • 交差軸(Cross Axis): 主軸に垂直な方向(デフォルトは縦)

コンテナのプロパティ

flex-direction(並ぶ方向)

.container { flex-direction: row; }            /* 横並び(デフォルト) */
.container { flex-direction: row-reverse; }    /* 横並び(逆順) */
.container { flex-direction: column; }         /* 縦並び */
.container { flex-direction: column-reverse; } /* 縦並び(逆順) */

justify-content(主軸の配置)

.container { justify-content: flex-start; }    /* 左寄せ(デフォルト) */
.container { justify-content: flex-end; }      /* 右寄せ */
.container { justify-content: center; }        /* 中央 */
.container { justify-content: space-between; } /* 両端揃え、等間隔 */
.container { justify-content: space-around; }  /* 各アイテムの周囲に等間隔 */
.container { justify-content: space-evenly; }  /* すべての間隔が等しい */

align-items(交差軸の配置)

.container { align-items: stretch; }           /* 高さを揃える(デフォルト) */
.container { align-items: flex-start; }        /* 上揃え */
.container { align-items: flex-end; }          /* 下揃え */
.container { align-items: center; }            /* 中央揃え */
.container { align-items: baseline; }          /* テキストのベースライン揃え */

gap(アイテム間の余白)

.container {
  display: flex;
  gap: 16px;        /* 行・列両方 */
  gap: 16px 24px;   /* 行間 16px、列間 24px */
}

gapmargin で余白を設定するよりも簡潔です。最初と最後のアイテムに余分な margin が付かないのも利点です。

flex-wrap(折り返し)

.container { flex-wrap: nowrap; }  /* 折り返さない(デフォルト) */
.container { flex-wrap: wrap; }    /* 折り返す */

wrap を指定すると、コンテナの幅を超えたアイテムが次の行に折り返します。レスポンシブデザインで必須の設定です。

アイテムのプロパティ

flex-grow(余白の分配)

.item-a { flex-grow: 1; }  /* 余白を1の比率で取得 */
.item-b { flex-grow: 2; }  /* 余白を2の比率で取得(Aの2倍) */
.item-c { flex-grow: 0; }  /* 余白を取らない(デフォルト) */

flex-shrink(縮小の比率)

.item { flex-shrink: 1; }  /* 均等に縮む(デフォルト) */
.item { flex-shrink: 0; }  /* 縮まない(固定幅を維持) */

flex-basis(基準サイズ)

.item { flex-basis: 200px; }  /* 初期幅 200px */
.item { flex-basis: 33.33%; } /* 初期幅 33.33% */
.item { flex-basis: auto; }   /* コンテンツに合わせる(デフォルト) */

flex ショートハンド(推奨)

/* flex: grow shrink basis */
.item { flex: 1; }           /* flex: 1 1 0% — 均等に分配 */
.item { flex: 0 0 200px; }   /* 固定幅 200px、伸縮しない */
.item { flex: 2 1 auto; }    /* 余白を2倍取る、コンテンツ幅ベース */

order(表示順序)

.item-a { order: 2; }  /* 2番目に表示 */
.item-b { order: 1; }  /* 1番目に表示 */
.item-c { order: 3; }  /* 3番目に表示 */

HTML の順序を変えずに表示順序だけ変えられます。ただし、スクリーンリーダーは HTML の順序で読み上げるため、アクセシビリティに注意してください。

実践パターン

ナビゲーションバー

<nav class="navbar">
  <div class="logo">CLAN</div>
  <ul class="nav-links">
    <li><a href="#">ホーム</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">サービス</a></li>
    <li><a href="#">お問い合わせ</a></li>
  </ul>
</nav>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background-color: #1a1a2e;
}

.logo {
  font-size: 1.5rem;
  font-weight: 700;
  color: white;
}

.nav-links {
  display: flex;
  list-style: none;
  gap: 24px;
}

.nav-links a {
  color: #e0e0e0;
  text-decoration: none;
}

.nav-links a:hover {
  color: white;
}

カードレイアウト(3列)

.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.card {
  flex: 1 1 calc(33.33% - 16px);
  min-width: 280px;
  padding: 24px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

min-width: 280pxflex-wrap: wrap の組み合わせで、画面幅に応じて自動的に列数が変わります。

完全中央寄せ

.center-box {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

Flexbox 以前は垂直中央寄せが CSS 最大の難問でした。今は3行で実現できます。

フッター(左・中央・右の3分割)

.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px;
}

.footer-left { }
.footer-center { text-align: center; }
.footer-right { text-align: right; }

デバッグのコツ

Chrome DevTools で Flexbox をデバッグ:

  1. Elements タブでフレックスコンテナを選択
  2. display: flex の横に flex バッジ が表示される
  3. バッジをクリックすると、オーバーレイでアイテムの配置が可視化される
  4. Styles パネルでプロパティをリアルタイムに変更して確認

実践ワーク

  1. ナビゲーションバーを Flexbox で作成(ロゴ左、メニュー右)
  2. 3列のカードレイアウトを作成(flex-wrap: wrap + min-width
  3. フッターを3分割(著作権表示・リンク・SNSアイコン)
  4. Chrome DevTools の Flex オーバーレイで配置を確認

まとめと次回の準備

今回のポイント: - display: flex で子要素が横並びに - justify-content で主軸、align-items で交差軸の配置を制御 - gap でアイテム間の余白を設定 - flex-wrap: wrap でレスポンシブな折り返し - flex: 1 で均等分配、flex: 0 0 200px で固定幅

次回: Module 2 に入り、CSS Grid を学びます。2次元レイアウト(行と列の同時制御)で、複雑なページ構造を直感的に作れるようになります。

参考文献: - MDN Web Docs「Flexbox」(https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Flexbox) - CSS-Tricks「A Complete Guide to Flexbox」(https://css-tricks.com/snippets/css/a-guide-to-flexbox/) - Flexbox Froggy — ゲームで学ぶ Flexbox(https://flexboxfroggy.com/)

Lecture 8CSS Grid — 2次元レイアウトをマスターする

12:00

CSS Grid — 2次元レイアウトをマスターする

Flexbox と Grid の使い分け

特徴 Flexbox CSS Grid
レイアウト次元 1次元(行 or 列) 2次元(行 and 列)
得意分野 ナビバー、カード横並び ページ全体のレイアウト
コンテンツ起点 コンテンツのサイズに合わせる グリッドの枠に合わせる
ブラウザ対応 99%+ 97%+

使い分けの目安: - 横一列(ナビ、ボタン群、カード列)→ Flexbox - 行と列の両方を制御(ページ構造、ダッシュボード)→ Grid - 迷ったら → まず Flexbox を試し、2次元の制御が必要なら Grid

Grid の基本

<div class="grid-container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;  /* 3列均等 */
  gap: 16px;
}

.item {
  padding: 24px;
  background-color: #007bff;
  color: white;
  text-align: center;
  border-radius: 4px;
}

これだけで 3列×2行 のグリッドが完成します。

grid-template-columns

列の幅を定義します。

/* 固定幅 */
grid-template-columns: 200px 200px 200px;

/* 均等分配(fr = fraction) */
grid-template-columns: 1fr 1fr 1fr;

/* 混在 */
grid-template-columns: 250px 1fr 1fr;  /* サイドバー250px + メイン2列 */

/* repeat() で繰り返し */
grid-template-columns: repeat(3, 1fr);     /* 1fr 1fr 1fr と同じ */
grid-template-columns: repeat(4, 200px);   /* 200px × 4列 */

/* auto-fill / auto-fit(レスポンシブ) */
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));

fr 単位

fr(fraction)は利用可能なスペースを比率で分配します。

grid-template-columns: 1fr 2fr 1fr;
/* 左: 25%, 中央: 50%, 右: 25% */

minmax()

grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  • minmax(280px, 1fr) : 最小280px、最大は残りスペースいっぱい
  • auto-fill : コンテナの幅に合わせて自動で列数を決定

これだけで メディアクエリなしのレスポンシブグリッド が実現します。

grid-template-rows

行の高さを定義します。

grid-template-rows: 80px 1fr 60px;   /* ヘッダー80px、メイン伸縮、フッター60px */
grid-template-rows: auto;            /* コンテンツに合わせる */
grid-template-rows: repeat(3, 200px); /* 200px × 3行 */

gap(余白)

gap: 16px;              /* 行間・列間とも 16px */
gap: 16px 24px;         /* 行間 16px、列間 24px */
row-gap: 16px;          /* 行間のみ */
column-gap: 24px;       /* 列間のみ */

アイテムの配置

grid-column / grid-row

.item-wide {
  grid-column: 1 / 3;    /* 1列目から3列目の手前まで(2列分) */
}

.item-tall {
  grid-row: 1 / 3;       /* 1行目から3行目の手前まで(2行分) */
}

.item-span {
  grid-column: span 2;   /* 2列分の幅 */
  grid-row: span 2;      /* 2行分の高さ */
}

grid-template-areas(名前付きエリア)

最も直感的なレイアウト方法です。

.page-layout {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 80px 1fr 60px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
<div class="page-layout">
  <header class="header">ヘッダー</header>
  <aside class="sidebar">サイドバー</aside>
  <main class="main">メインコンテンツ</main>
  <footer class="footer">フッター</footer>
</div>

ASCII アートのようにレイアウトを「描ける」のが Grid の強みです。

実践パターン

Holy Grail レイアウト(王道のページ構成)

.holy-grail {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header  header"
    "nav    content sidebar"
    "footer footer  footer";
  min-height: 100vh;
  gap: 16px;
}

.hg-header  { grid-area: header;  background: #1a1a2e; color: white; padding: 16px; }
.hg-nav     { grid-area: nav;     background: #f0f0f0; padding: 16px; }
.hg-content { grid-area: content; padding: 16px; }
.hg-sidebar { grid-area: sidebar; background: #f0f0f0; padding: 16px; }
.hg-footer  { grid-area: footer;  background: #333; color: white; padding: 16px; }

画像ギャラリー

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 8px;
}

.gallery img {
  width: 100%;
  height: 250px;
  object-fit: cover;
  border-radius: 4px;
}

/* 特定の画像を大きく */
.gallery .featured {
  grid-column: span 2;
  grid-row: span 2;
}

.gallery .featured img {
  height: 100%;
}

object-fit: cover は画像のアスペクト比を維持しつつ、指定サイズいっぱいに表示します。

ダッシュボード風レイアウト

.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: auto auto 1fr;
  gap: 16px;
  padding: 16px;
}

.stat-card { padding: 24px; background: white; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.12); }
.chart-main { grid-column: span 3; }
.chart-side { grid-column: span 1; }
.table-full { grid-column: span 4; }

Grid と Flexbox の組み合わせ

ページ全体の骨組みは Grid、コンポーネント内部は Flexbox というのが現代のベストプラクティスです。

/* ページ構造 = Grid */
.page {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

/* ナビバー内部 = Flexbox */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
}

/* カードグリッド = Grid */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}

/* カード内部 = Flexbox */
.card {
  display: flex;
  flex-direction: column;
  padding: 24px;
}

.card-footer {
  margin-top: auto;  /* フッターを最下部に押し下げ */
}

デバッグ

Chrome DevTools で Grid レイアウトを可視化:

  1. Elements タブで Grid コンテナを選択
  2. display: grid 横の grid バッジ をクリック
  3. グリッドライン(列・行の番号付き)がオーバーレイ表示される
  4. Layout パネル → Grid overlays で表示設定をカスタマイズ

実践ワーク

  1. grid-template-areas でヘッダー/サイドバー/メイン/フッターのページ構造を作成
  2. repeat(auto-fill, minmax(280px, 1fr)) でレスポンシブカードグリッドを作成
  3. 画像ギャラリーを作成し、1枚だけ span 2 で大きく表示
  4. DevTools の Grid オーバーレイで行番号・列番号を確認

まとめと次回の準備

今回のポイント: - Grid は2次元レイアウト(行 and 列)に最適 - fr 単位と repeat() で柔軟な列定義 - grid-template-areas で視覚的にレイアウトを「描ける」 - repeat(auto-fill, minmax()) でメディアクエリなしのレスポンシブ - Grid(骨組み)+ Flexbox(コンポーネント内部)が現代のベストプラクティス

次回: レスポンシブデザイン。メディアクエリ、モバイルファーストの設計思想、ビューポート単位を使って、どんな画面でも美しく表示する方法を学びます。

参考文献: - MDN Web Docs「CSS Grid Layout」(https://developer.mozilla.org/ja/docs/Web/CSS/CSS_grid_layout) - CSS-Tricks「A Complete Guide to CSS Grid」(https://css-tricks.com/snippets/css/complete-guide-grid/) - Grid Garden — ゲームで学ぶ CSS Grid(https://cssgridgarden.com/)

Lecture 9レスポンシブデザイン — どんな画面でも美しく表示する

12:00

レスポンシブデザイン — どんな画面でも美しく表示する

なぜレスポンシブが必須なのか

Statcounter(2024年)によると、全世界の Web トラフィックの約 60% がモバイルデバイスからです。Google は 2019年からモバイルファーストインデックスを採用しており、モバイル対応していないサイトは検索順位が下がります。

レスポンシブデザイン(RWD) は、1つの HTML で画面サイズに応じてレイアウトを変化させる設計手法です。Ethan Marcotte が 2010年に「A List Apart」で提唱しました。

viewport メタタグ

すべてのレスポンシブサイトに必須の設定です。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
属性 意味
width device-width ビューポート幅をデバイス幅に合わせる
initial-scale 1.0 初期ズーム倍率

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

メディアクエリ

画面幅に応じて CSS を切り替える仕組みです。

基本構文

/* 画面幅が 768px 以下のとき */
@media (max-width: 768px) {
  .container {
    padding: 0 16px;
  }
}

/* 画面幅が 769px 以上のとき */
@media (min-width: 769px) {
  .container {
    max-width: 1200px;
    margin: 0 auto;
  }
}

モバイルファーストアプローチ(推奨)

モバイル向けのスタイルをベースに書き、画面が大きくなるにつれて min-width でスタイルを追加する方法です。

/* ベース: モバイル(320px〜) */
.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

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

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

なぜモバイルファーストか

  1. パフォーマンス: モバイルは回線が遅い。最小限の CSS から始める
  2. 優先順位: コンテンツの本質に集中できる(小さい画面に収まるものが本当に必要な情報)
  3. Google推奨: モバイルファーストインデックスとの整合性

一般的なブレークポイント

/* スマートフォン: 〜767px(ベース、メディアクエリ不要) */

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

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

/* 大画面 */
@media (min-width: 1440px) { }

ブレークポイントはデバイスの幅ではなく、レイアウトが崩れるポイント で設定するのが理想です。

レスポンシブな単位

ビューポート単位

.hero {
  height: 100vh;           /* ビューポートの高さ100% */
  width: 100vw;            /* ビューポートの幅100% */
}

.section {
  min-height: 50vh;        /* 画面の半分以上の高さ */
  padding: 5vw;            /* 画面幅の5% */
}
単位 意味
vw ビューポート幅の1%
vh ビューポート高さの1%
vmin vw と vh の小さい方
vmax vw と vh の大きい方
dvh 動的ビューポート高さ(モバイルのアドレスバー考慮)

注意: モバイルブラウザでは 100vh がアドレスバーを含む場合があり、コンテンツがはみ出すことがあります。100dvh を使うか、JavaScript で補正してください。

パーセント

.container {
  width: 90%;
  max-width: 1200px;
  margin: 0 auto;
}

.sidebar {
  width: 30%;
}

.main-content {
  width: 70%;
}

clamp()(最小・推奨・最大を一度に指定)

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

.container {
  padding: clamp(16px, 3vw, 48px);
  /* 画面幅に応じて16px〜48pxの間で自動調整 */
}

clamp() を使えば、フォントサイズ用のメディアクエリが不要になります。

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

デスクトップ: 横並び / モバイル: ハンバーガーメニュー

<nav class="navbar">
  <div class="logo">CLAN</div>
  <button class="menu-toggle" aria-label="メニュー" aria-expanded="false"></button>
  <ul class="nav-links">
    <li><a href="#">ホーム</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">サービス</a></li>
    <li><a href="#">お問い合わせ</a></li>
  </ul>
</nav>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: #1a1a2e;
}

.logo { color: white; font-size: 1.5rem; font-weight: 700; }

.menu-toggle {
  display: none;
  background: none;
  border: none;
  color: white;
  font-size: 1.5rem;
  cursor: pointer;
}

.nav-links {
  display: flex;
  list-style: none;
  gap: 24px;
}

.nav-links a {
  color: #e0e0e0;
  text-decoration: none;
}

/* モバイル */
@media (max-width: 767px) {
  .menu-toggle {
    display: block;
  }

  .nav-links {
    display: none;
    flex-direction: column;
    position: absolute;
    top: 60px;
    left: 0;
    right: 0;
    background: #1a1a2e;
    padding: 16px;
    gap: 16px;
  }

  .nav-links.active {
    display: flex;
  }
}

ハンバーガーメニューの開閉は JavaScript で .active クラスをトグルします(JavaScript コースで詳しく学びます)。

<script>
  document.querySelector('.menu-toggle').addEventListener('click', function() {
    const nav = document.querySelector('.nav-links');
    const expanded = this.getAttribute('aria-expanded') === 'true';
    nav.classList.toggle('active');
    this.setAttribute('aria-expanded', !expanded);
  });
</script>

レスポンシブな画像

/* 基本: 親要素からはみ出さない */
img {
  max-width: 100%;
  height: auto;
}

picture 要素(画面サイズで画像を切り替え)

<picture>
  <source media="(min-width: 1024px)" srcset="images/hero-desktop.jpg">
  <source media="(min-width: 768px)" srcset="images/hero-tablet.jpg">
  <img src="images/hero-mobile.jpg" alt="ヒーロー画像">
</picture>

モバイルでは小さい画像、デスクトップでは大きい画像を配信することで、通信量を削減できます。

レスポンシブなテーブル

テーブルはモバイルで崩れやすい要素です。

/* テーブルを横スクロール可能にする */
.table-wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
<div class="table-wrapper">
  <table>
    <!-- テーブル内容 -->
  </table>
</div>

テスト方法

Chrome DevTools のデバイスモード

  1. F12 → 左上の「Toggle device toolbar」(スマホアイコン)をクリック
  2. 上部でデバイスを選択(iPhone, iPad, Pixel 等)
  3. 画面幅をドラッグで自由に変更
  4. レスポンシブモードで「Responsive」を選択し、幅を手動入力

テストすべきポイント

確認項目 チェック
テキストが画面外にはみ出していないか
画像が親要素からはみ出していないか
横スクロールが発生していないか
タップターゲット(ボタン・リンク)が 44×44px 以上か
フォントサイズが小さすぎないか(最低16px推奨)

Google の「PageSpeed Insights」(https://pagespeed.web.dev/)でモバイル対応状況を自動チェックできます。

実践ワーク

  1. モバイルファーストで新しいスタイルシートを書く(ベース = 1カラム)
  2. @media (min-width: 768px) でタブレット用(2カラム)を追加
  3. @media (min-width: 1024px) でデスクトップ用(3カラム + サイドバー)を追加
  4. ハンバーガーメニューを実装
  5. Chrome DevTools のデバイスモードで各画面幅をテスト

まとめと次回の準備

今回のポイント: - viewport メタタグは全ページに必須 - モバイルファースト: ベースをモバイル向けに書き、min-width で拡張 - clamp() でメディアクエリなしのレスポンシブ文字サイズ - repeat(auto-fill, minmax()) でレスポンシブグリッド - Chrome DevTools のデバイスモードでテスト

次回(最終回): これまでの全スキルを統合して、ポートフォリオサイトを1から作り上げます。

参考文献: - Ethan Marcotte「Responsive Web Design」(A List Apart, 2010) - Google「モバイルファーストインデックス」(https://developers.google.com/search/docs/crawling-indexing/mobile/mobile-sites-mobile-first-indexing) - MDN Web Docs「レスポンシブデザイン」(https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Responsive_Design) - Statcounter Global Stats(https://gs.statcounter.com/)

Lecture 10総合演習 — ポートフォリオサイトを作ろう

15:00

総合演習 — ポートフォリオサイトを作ろう

この講座で学んだスキルの全体像

9つの講義を通じて、Web サイト制作の基礎を一通り学びました。最終回では、すべてのスキルを統合して ポートフォリオサイト を完成させます。

講義 学んだスキル 本演習での活用
第1回 Web の仕組み、開発環境 VS Code + Live Server で開発
第2回 HTML 基本タグ コンテンツの構造化
第3回 セマンティック HTML、フォーム ページ構造、お問い合わせ
第4回 CSS セレクタ、カスケード スタイリング全般
第5回 ボックスモデル、余白設計 レイアウトの余白
第6回 カラー、タイポグラフィ 配色とフォント
第7回 Flexbox ナビバー、カード横並び
第8回 CSS Grid ページ全体のレイアウト
第9回 レスポンシブデザイン モバイル対応

完成イメージ

ページ構成(シングルページ)

┌─────────────────────────────────────────┐
│  ナビゲーション(Flexbox)               │
├─────────────────────────────────────────┤
│  ヒーローセクション(Flexbox中央寄せ)    │
├─────────────────────────────────────────┤
│  自己紹介セクション                      │
├─────────────────────────────────────────┤
│  スキルセクション(Grid 3列)            │
├─────────────────────────────────────────┤
│  制作実績セクション(Grid ギャラリー)    │
├─────────────────────────────────────────┤
│  お問い合わせフォーム                     │
├─────────────────────────────────────────┤
│  フッター                                │
└─────────────────────────────────────────┘

ファイル構造

portfolio/
├── index.html
├── css/
│   └── style.css
└── images/
    ├── profile.jpg
    ├── work-1.jpg
    ├── work-2.jpg
    └── work-3.jpg

画像は Unsplash(https://unsplash.com/)から無料でダウンロードできます。

Step 1: HTML の骨組み

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="田中太郎のポートフォリオサイト。Web制作の実績を紹介します。">
  <title>田中太郎 | Webデザイナー ポートフォリオ</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <!-- ナビゲーション -->
  <header class="header">
    <nav class="navbar">
      <div class="logo">T.Tanaka</div>
      <button class="menu-toggle" aria-label="メニュー" aria-expanded="false"></button>
      <ul class="nav-links">
        <li><a href="#about">About</a></li>
        <li><a href="#skills">Skills</a></li>
        <li><a href="#works">Works</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <!-- ヒーロー -->
    <section class="hero">
      <div class="hero-content">
        <h1>こんにちは、田中太郎です</h1>
        <p>Web デザイナー / フロントエンドエンジニア</p>
        <a href="#works" class="btn btn-primary">制作実績を見る</a>
      </div>
    </section>

    <!-- 自己紹介 -->
    <section id="about" class="section">
      <div class="container">
        <h2 class="section-title">About</h2>
        <div class="about-grid">
          <figure class="about-image">
            <img src="images/profile.jpg" alt="田中太郎のプロフィール写真" width="400" height="400">
          </figure>
          <div class="about-text">
            <p>Web制作歴3年のフリーランスです。HTML/CSSを中心に、レスポンシブ対応のモダンなWebサイトを制作しています。</p>
            <p>ユーザーにとって使いやすく、ビジネスの成果につながるデザインを心がけています。</p>
          </div>
        </div>
      </div>
    </section>

    <!-- スキル -->
    <section id="skills" class="section section-alt">
      <div class="container">
        <h2 class="section-title">Skills</h2>
        <div class="skills-grid">
          <div class="skill-card">
            <h3>HTML / CSS</h3>
            <p>セマンティックHTML、Flexbox、Grid、レスポンシブデザイン</p>
          </div>
          <div class="skill-card">
            <h3>JavaScript</h3>
            <p>DOM操作、非同期処理、React基礎</p>
          </div>
          <div class="skill-card">
            <h3>デザイン</h3>
            <p>Figma、配色設計、タイポグラフィ</p>
          </div>
        </div>
      </div>
    </section>

    <!-- 制作実績 -->
    <section id="works" class="section">
      <div class="container">
        <h2 class="section-title">Works</h2>
        <div class="works-grid">
          <article class="work-card">
            <img src="images/work-1.jpg" alt="企業サイトの制作実績" width="600" height="400">
            <div class="work-info">
              <h3>株式会社〇〇 コーポレートサイト</h3>
              <p>レスポンシブ対応のコーポレートサイト。モバイルファーストで設計。</p>
              <span class="tag">HTML/CSS</span>
              <span class="tag">JavaScript</span>
            </div>
          </article>
          <article class="work-card">
            <img src="images/work-2.jpg" alt="ECサイトの制作実績" width="600" height="400">
            <div class="work-info">
              <h3>△△ショップ ECサイト</h3>
              <p>商品一覧・カート機能を実装したECサイト。</p>
              <span class="tag">HTML/CSS</span>
              <span class="tag">React</span>
            </div>
          </article>
          <article class="work-card">
            <img src="images/work-3.jpg" alt="ブログサイトの制作実績" width="600" height="400">
            <div class="work-info">
              <h3>個人ブログ</h3>
              <p>読みやすさにこだわったブログテンプレート。</p>
              <span class="tag">HTML/CSS</span>
              <span class="tag">WordPress</span>
            </div>
          </article>
        </div>
      </div>
    </section>

    <!-- お問い合わせ -->
    <section id="contact" class="section section-alt">
      <div class="container">
        <h2 class="section-title">Contact</h2>
        <form class="contact-form" action="#" method="POST">
          <div class="form-group">
            <label for="name">お名前</label>
            <input type="text" id="name" name="name" required placeholder="山田花子">
          </div>
          <div class="form-group">
            <label for="email">メールアドレス</label>
            <input type="email" id="email" name="email" required placeholder="example@mail.com">
          </div>
          <div class="form-group">
            <label for="message">メッセージ</label>
            <textarea id="message" name="message" rows="5" required placeholder="ご用件をお書きください"></textarea>
          </div>
          <button type="submit" class="btn btn-primary">送信</button>
        </form>
      </div>
    </section>
  </main>

  <footer class="footer">
    <div class="container">
      <p>&copy; 2025 T.Tanaka. All rights reserved.</p>
    </div>
  </footer>

  <script>
    document.querySelector('.menu-toggle').addEventListener('click', function() {
      const nav = document.querySelector('.nav-links');
      const expanded = this.getAttribute('aria-expanded') === 'true';
      nav.classList.toggle('active');
      this.setAttribute('aria-expanded', !expanded);
    });
  </script>
</body>
</html>

Step 2: CSS スタイリング

/* ========================
   CSS Reset & Base
   ======================== */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --color-primary: #2563eb;
  --color-primary-dark: #1d4ed8;
  --color-bg: #ffffff;
  --color-bg-alt: #f8fafc;
  --color-text: #1e293b;
  --color-text-light: #64748b;
  --color-border: #e2e8f0;
  --font-base: "Noto Sans JP", sans-serif;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 48px;
  --space-2xl: 80px;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-base);
  font-size: 1rem;
  line-height: 1.8;
  color: var(--color-text);
  background-color: var(--color-bg);
}

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

a {
  color: var(--color-primary);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* ========================
   Layout
   ======================== */
.container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--space-lg);
}

.section {
  padding: var(--space-2xl) 0;
}

.section-alt {
  background-color: var(--color-bg-alt);
}

.section-title {
  font-size: clamp(1.5rem, 4vw, 2rem);
  text-align: center;
  margin-bottom: var(--space-xl);
  position: relative;
}

.section-title::after {
  content: "";
  display: block;
  width: 60px;
  height: 3px;
  background-color: var(--color-primary);
  margin: var(--space-sm) auto 0;
}

/* ========================
   Header & Navigation
   ======================== */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-border);
}

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-md) var(--space-lg);
  max-width: 1100px;
  margin: 0 auto;
}

.logo {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-text);
}

.menu-toggle {
  display: none;
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  color: var(--color-text);
}

.nav-links {
  display: flex;
  list-style: none;
  gap: var(--space-lg);
}

.nav-links a {
  color: var(--color-text-light);
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.nav-links a:hover {
  color: var(--color-primary);
  text-decoration: none;
}

/* ========================
   Hero
   ======================== */
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 80vh;
  text-align: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

.hero h1 {
  font-size: clamp(1.75rem, 5vw, 3rem);
  margin-bottom: var(--space-md);
}

.hero p {
  font-size: clamp(1rem, 2.5vw, 1.25rem);
  opacity: 0.9;
  margin-bottom: var(--space-lg);
}

/* ========================
   Buttons
   ======================== */
.btn {
  display: inline-block;
  padding: 12px 32px;
  border: none;
  border-radius: 6px;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.2s, transform 0.1s;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

.btn-primary {
  background-color: var(--color-primary);
  color: white;
}

.btn-primary:hover {
  background-color: var(--color-primary-dark);
}

/* ========================
   About
   ======================== */
.about-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
  align-items: center;
}

.about-image img {
  border-radius: 50%;
  width: 200px;
  height: 200px;
  object-fit: cover;
  margin: 0 auto;
}

.about-text p {
  margin-bottom: var(--space-md);
  color: var(--color-text-light);
}

@media (min-width: 768px) {
  .about-grid {
    grid-template-columns: auto 1fr;
  }
}

/* ========================
   Skills
   ======================== */
.skills-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-lg);
}

.skill-card {
  padding: var(--space-lg);
  background: white;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  text-align: center;
}

.skill-card h3 {
  margin-bottom: var(--space-sm);
  color: var(--color-primary);
}

.skill-card p {
  font-size: 0.875rem;
  color: var(--color-text-light);
}

/* ========================
   Works
   ======================== */
.works-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-lg);
}

.work-card {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  transition: transform 0.2s, box-shadow 0.2s;
}

.work-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.work-card img {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.work-info {
  padding: var(--space-lg);
}

.work-info h3 {
  margin-bottom: var(--space-sm);
}

.work-info p {
  font-size: 0.875rem;
  color: var(--color-text-light);
  margin-bottom: var(--space-md);
}

.tag {
  display: inline-block;
  padding: 2px 10px;
  background-color: var(--color-bg-alt);
  border-radius: 4px;
  font-size: 0.75rem;
  color: var(--color-text-light);
  margin-right: 4px;
}

/* ========================
   Contact Form
   ======================== */
.contact-form {
  max-width: 600px;
  margin: 0 auto;
}

.form-group {
  margin-bottom: var(--space-lg);
}

.form-group label {
  display: block;
  margin-bottom: var(--space-sm);
  font-weight: 700;
  font-size: 0.875rem;
}

.form-group input,
.form-group textarea {
  width: 100%;
  padding: 12px 16px;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  font-family: var(--font-base);
  font-size: 1rem;
  transition: border-color 0.2s;
}

.form-group input:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

/* ========================
   Footer
   ======================== */
.footer {
  background: var(--color-text);
  color: var(--color-text-light);
  text-align: center;
  padding: var(--space-lg) 0;
  font-size: 0.875rem;
}

/* ========================
   Responsive (Mobile)
   ======================== */
@media (max-width: 767px) {
  .menu-toggle {
    display: block;
  }

  .nav-links {
    display: none;
    flex-direction: column;
    position: absolute;
    top: 56px;
    left: 0;
    right: 0;
    background: rgba(255, 255, 255, 0.98);
    padding: var(--space-md);
    gap: var(--space-md);
    border-bottom: 1px solid var(--color-border);
  }

  .nav-links.active {
    display: flex;
  }
}

Step 3: 確認チェックリスト

# 確認項目 チェック
1 HTML が W3C Validator(https://validator.w3.org/)でエラーなし
2 すべての <img>alt 属性がある
3 見出しの階層(h1→h2→h3)が正しい
4 Chrome DevTools のデバイスモードでスマホ表示が崩れない
5 ナビリンク(#about, #skills 等)で正しい位置にスクロールする
6 フォームの required バリデーションが機能する
7 テキストと背景のコントラスト比が 4.5:1 以上
8 scroll-behavior: smooth でスムーズスクロールする

公開する方法

ポートフォリオサイトを無料で公開できるサービス:

サービス 特徴 URL
GitHub Pages GitHub リポジトリから直接公開 pages.github.com
Netlify ドラッグ&ドロップで即デプロイ netlify.com
Vercel Git 連携で自動デプロイ vercel.com

GitHub Pages での公開手順

  1. GitHub でリポジトリを作成(例: my-portfolio
  2. ポートフォリオのファイルを push
  3. Settings → Pages → Source を「main」ブランチに設定
  4. https://ユーザー名.github.io/my-portfolio/ で公開される

この講座の振り返りと次のステップ

学んだこと

HTML: 文書構造、セマンティックタグ、フォーム、アクセシビリティ

CSS: セレクタ、ボックスモデル、Flexbox、Grid、レスポンシブデザイン

ツール: VS Code、Chrome DevTools、Google Fonts

さらに学びたい方へ

方向性 内容 リソース
JavaScript DOM操作、イベント処理、非同期 当プラットフォームの「JavaScript入門」コース
CSS設計 BEM、FLOCSS、Tailwind CSS MDN Web Docs
アニメーション CSS transition、animation、keyframes MDN Web Docs
アクセシビリティ WCAG 2.1、ARIA W3C WAI
パフォーマンス Core Web Vitals、画像最適化 web.dev

最後に

Web サイトはテキストエディタとブラウザがあれば誰でも作れます。特別なソフトも高価な機材も不要です。この講座で学んだ HTML と CSS は、Web 技術の基礎であり、20 年以上変わらない根幹です。フレームワークやツールは移り変わりますが、基礎を理解していればどんな変化にも対応できます。

まずはこのポートフォリオを自分なりにカスタマイズして公開してみてください。公開された Web サイトは、あなたのスキルを証明する最高のポートフォリオです。

参考文献: - MDN Web Docs(https://developer.mozilla.org/ja/) - W3C HTML/CSS 仕様(https://www.w3.org/standards/webdesign/) - Google web.dev(https://web.dev/) - GitHub Pages(https://pages.github.com/)