この章では、HTMLとCSSの基礎を学び、レスポンシブな個人プロフィールページを作成します。
- ブラウザがHTMLをどのように解釈し描画するかを理解する
- CSSがどのように適用されるかのメカニズムを理解する
- HTMLの基本構造とセマンティックタグ
- CSSのセレクタとスタイリング
- Flexbox・Gridレイアウト
- レスポンシブデザインの実装
- Tailwind CSSの活用
成果物: 個人プロフィールページ
最も重要な質問: 「なぜHTMLファイルを開くと、画面に文字や画像が表示されるのか?」
この答えを理解することが、Web開発の基礎です。
全体の流れ:
1. HTMLファイルを開く
↓
2. ブラウザがファイルを読み込む
↓
3. HTMLを上から下へパース(解析)する
↓
4. DOMツリーを構築する
↓
5. CSSを読み込んで適用する
↓
6. CSSOMツリーを構築する
↓
7. レンダーツリーを構築する
↓
8. レイアウトを計算する
↓
9. 画面に描画(ペイント)する
ステップ1-2: HTMLファイルの読み込み
あなたがブラウザで index.html を開くと、ブラウザはファイルの中身を読み取ります:
<!DOCTYPE html>
<html>
<head>
<title>私のページ</title>
</head>
<body>
<h1>こんにちは</h1>
<p>これは段落です</p>
</body>
</html>ステップ3: パース(解析)
ブラウザは、HTMLを「上から順番に」読んでいきます。このプロセスを「パース(構文解析)」と呼びます。
読み取り順序:
1行目: <!DOCTYPE html> → 「これはHTML5だ」と認識
2行目: <html> → 「HTML文書の開始」
3行目: <head> → 「メタ情報の開始」
4行目: <title>私のページ</title> → 「タイトルは"私のページ"」
...
ステップ4: DOMツリーの構築
ブラウザは、読み取ったHTMLを「木構造(ツリー)」に変換します。これを DOM(Document Object Model) と呼びます。
視覚的な表現:
HTMLコード:
<html>
<head>
<title>私のページ</title>
</head>
<body>
<h1>こんにちは</h1>
<p>これは段落です</p>
</body>
</html>
↓ ブラウザが内部で作るDOMツリー:
html
/ \
head body
| / \
title h1 p
| | |
"私の "こん "これは
ページ" にちは" 段落です"
なぜツリー構造にするのか:
- 親子関係を明確にする:
<body>の中に<h1>がある、という関係を記憶 - 効率的に検索する: JavaScriptで「h1要素を探して」と言ったとき、すぐに見つけられる
- スタイルの継承: 親要素のスタイルが子要素に引き継がれる仕組みを実現
ステップ5-6: CSSの読み込みとCSSOMツリー
HTMLと同じように、CSSも解析されてツリー構造になります:
h1 {
color: blue;
font-size: 32px;
}
p {
color: gray;
}これが以下のような構造(CSSOM = CSS Object Model)になります:
h1 → color: blue, font-size: 32px
p → color: gray
ステップ7: レンダーツリーの構築
DOMツリーとCSSOMツリーを組み合わせて、「実際に画面に表示するもの」のツリーを作ります。
DOMツリー + CSSOMツリー = レンダーツリー
h1 "こんにちは"
├─ color: blue
└─ font-size: 32px
p "これは段落です"
└─ color: gray
ステップ8: レイアウト計算
各要素の「位置」と「サイズ」を計算します。これを レイアウト(またはリフロー) と呼びます。
画面の幅: 1200px
画面の高さ: 800px
h1要素:
- 位置: 左上から (0px, 0px)
- サイズ: 幅 1200px, 高さ 40px
- フォントサイズ: 32px
p要素:
- 位置: 左上から (0px, 40px) ← h1の下
- サイズ: 幅 1200px, 高さ 20px
- フォントサイズ: 16px (デフォルト)
ステップ9: 描画(ペイント)
最後に、計算された情報をもとに、実際に画面のピクセルに色を塗ります。
(0, 0) から (1200, 40) の範囲に:
- 青色で "こんにちは" という文字を32pxのサイズで描く
(0, 40) から (1200, 60) の範囲に:
- 灰色で "これは段落です" という文字を16pxのサイズで描く
結果: あなたの目に見える画面が完成します。
このレンダリングプロセスを理解すると、以下のことが分かるようになります:
1. なぜページの読み込みが遅いのか
HTML (大) → パースに時間
CSS (複雑) → スタイル計算に時間
画像 (大) → ダウンロードに時間
→ 最適化が必要
2. なぜJavaScriptでDOMを変更すると画面が更新されるのか
JavaScript で要素を変更
↓
DOMツリーが変わる
↓
レンダーツリーが再構築
↓
レイアウト再計算
↓
再描画
→ 画面が更新される
3. なぜCSSの書き方でパフォーマンスが変わるのか
複雑なセレクタ → マッチング計算に時間
多数の要素変更 → レイアウト再計算が頻発
→ シンプルなCSSが速い
HTMLの正式名称: HyperText Markup Language
分解すると:
- HyperText: リンクで繋がったテキスト(Webの本質)
- Markup: 印をつける、マークアップする
- Language: 言語
HTMLは「マークアップ言語」:
プログラミング言語ではありません。「この部分は見出し」「この部分は段落」と、文書に意味を与える言語です。
例え:
論文を書くとき:
普通のテキスト:
イントロダクション
これは研究の背景です...
マークアップしたテキスト:
<章タイトル>イントロダクション</章タイトル>
<段落>これは研究の背景です...</段落>
HTMLも同じことをしています:
<h1>イントロダクション</h1>
<p>これは研究の背景です...</p>なぜマークアップが必要なのか:
- ブラウザが理解できる: 「これは見出しだから大きく表示しよう」
- スタイルを適用できる: 「すべての見出しを青色に」
- 検索エンジンが理解できる: Googleが「これは重要な見出しだ」と認識
- アクセシビリティ: スクリーンリーダーが「これは見出しです」と読み上げ
HTMLは、Webページの構造を定義するマークアップ言語です。
最小限のHTML:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ページタイトル</title>
</head>
<body>
<!-- ここにコンテンツを記述 -->
</body>
</html>重要な要素:
<!DOCTYPE html>: HTML5であることを宣言<html lang="ja">: 言語を日本語に設定<head>: メタ情報(タイトル、文字コードなど)<body>: 表示されるコンテンツ
意味のあるタグを使うことで、コードの可読性とSEOが向上します。
<header>
<nav><!-- ナビゲーション --></nav>
</header>
<main>
<article>
<h1>記事タイトル</h1>
<section>
<h2>セクションタイトル</h2>
<p>本文...</p>
</section>
</article>
</main>
<footer>
<p>© 2025 Your Name</p>
</footer>よく使うセマンティックタグ:
<header>: ヘッダー<nav>: ナビゲーション<main>: メインコンテンツ<article>: 独立したコンテンツ<section>: セクション<aside>: サイドバー<footer>: フッター
<h1>見出し1(最も重要)</h1>
<h2>見出し2</h2>
<h3>見出し3</h3>
<p>段落</p>
<strong>太字(重要)</strong>
<em>斜体(強調)</em>
<a href="https://example.com">リンク</a><!-- 順序なしリスト -->
<ul>
<li>項目1</li>
<li>項目2</li>
</ul>
<!-- 順序付きリスト -->
<ol>
<li>ステップ1</li>
<li>ステップ2</li>
</ol><img src="/images/photo.jpg" alt="説明文" />CSSの正式名称: Cascading Style Sheets
分解すると:
- Cascading: 滝のように流れる、段階的に適用される
- Style: 見た目のスタイル
- Sheets: スタイルの集まり(シート)
CSSの役割:
HTMLが「構造」を定義するのに対し、CSSは「見た目」を定義します。
HTML = 骨格(構造)
CSS = 服(見た目)
JavaScript = 動き(動作)
なぜHTMLとCSSを分けるのか:
悪い例(昔の方法):
<h1>
<font color="blue" size="7">
<b>タイトル</b>
</font>
</h1>- 見た目がHTMLに混ざっている
- 100箇所のタイトルの色を変えたい → 100箇所修正が必要
- 構造が分かりにくい
良い例(CSSを使う方法):
<!-- HTML: 構造だけ -->
<h1>タイトル</h1>
<!-- CSS: 見た目だけ -->
h1 {
color: blue;
font-size: 48px;
font-weight: bold;
}- 構造と見た目が分離
- すべてのh1の色を変えたい → CSSの1箇所を修正するだけ
- 役割が明確
CSSが適用されるプロセス:
1. ブラウザがHTMLを読む
↓
2. <link>タグや<style>タグを見つける
↓
3. CSSファイルをダウンロード(または読み込み)
↓
4. CSSを解析(パース)
↓
5. 各HTML要素にマッチするCSSルールを探す
↓
6. 複数のルールがある場合、優先順位を決定(カスケード)
↓
7. 最終的なスタイルを計算
↓
8. レンダーツリーに適用
↓
9. 画面に描画
カスケード(Cascade)とは:
「カスケード」は「滝」という意味です。CSSでは、複数のスタイル定義が「上から下へ流れるように」適用されます。
例:
/* 1. ブラウザのデフォルト */
h1 {
font-size: 32px;
color: black;
}
/* 2. あなたが書いたCSS */
h1 {
color: blue;
}
/* 3. より具体的なCSS */
.title {
color: red;
}HTMLが以下の場合:
<h1 class="title">タイトル</h1>適用される順序:
1. デフォルト: font-size: 32px, color: black
↓(上書き)
2. あなたのCSS: color: blue (blackがblueに変わる)
↓(さらに上書き)
3. より具体的: color: red (blueがredに変わる)
最終結果:
font-size: 32px (デフォルトのまま)
color: red (最も具体的なものが勝つ)
詳細度(Specificity)- どのスタイルが勝つか:
複数のCSSルールが同じ要素に適用される場合、「詳細度」で優先順位が決まります。
詳細度の計算:
IDセレクタ = 100点
クラスセレクタ = 10点
要素セレクタ = 1点
例:
/* 1点 */
h1 { color: blue; }
/* 10点 */
.title { color: green; }
/* 100点 */
#main-title { color: red; }
/* 11点 (10 + 1) */
h1.title { color: purple; }
/* 110点 (100 + 10) */
#main-title.title { color: orange; }HTMLが以下の場合:
<h1 id="main-title" class="title">タイトル</h1>勝者は #main-title.title (110点) で、色は orange になります。
!important - 強制的に勝つ方法:
h1 {
color: blue !important;
}
#main-title {
color: red; /* これは無視される */
}ただし、!important の乱用は避けるべきです。コードが管理しにくくなります。
継承(Inheritance):
一部のCSSプロパティは、親要素から子要素に自動的に引き継がれます。
継承されるプロパティの例:
color(文字色)font-family(フォント)font-size(文字サイズ)line-height(行の高さ)
継承されないプロパティの例:
border(枠線)padding(余白)margin(マージン)background(背景)
例:
body {
color: blue;
font-size: 16px;
}<body>
<div>
<p>このテキストは青色で16pxになる</p>
<span>これも青色で16pxになる</span>
</div>
</body>なぜ継承するのか:
- 効率的: すべての要素に同じスタイルを書く必要がない
- 一貫性: サイト全体で統一感が出る
CSSは、HTMLに見た目を与えるスタイルシート言語です。
セレクタ {
プロパティ: 値;
}各部分の意味:
h1 { /* セレクタ: どの要素にスタイルを適用するか */
color: blue; /* プロパティ: 値 = 何をどうするか */
}- セレクタ: スタイルを適用する対象を指定
- プロパティ: 変更したい見た目の種類(色、サイズ、位置など)
- 値: プロパティに設定する具体的な値
例:
h1 {
color: blue; /* 文字色を青に */
font-size: 32px; /* 文字サイズを32pxに */
font-weight: bold; /* 文字を太字に */
}複数のセレクタに同じスタイル:
h1, h2, h3 {
color: navy;
}コメントの書き方:
/* これはコメントです */
h1 {
color: blue; /* 行末にも書けます */
}/* 要素セレクタ */
p { color: black; }
/* クラスセレクタ */
.text-blue { color: blue; }
/* IDセレクタ */
#header { background: white; }
/* 子孫セレクタ */
.container p { margin: 10px; }
/* 直接の子要素 */
.container > p { padding: 5px; }
/* 疑似クラス */
a:hover { color: red; }
button:active { opacity: 0.8; }すべてのHTML要素は「箱」として扱われます。
┌─────────────────────────┐
│ Margin(外側余白) │
│ ┌───────────────────┐ │
│ │ Border(枠線) │ │
│ │ ┌─────────────┐ │ │
│ │ │Padding(内側余白)│ │
│ │ │ ┌───────┐ │ │ │
│ │ │ │Content│ │ │ │
│ │ │ └───────┘ │ │ │
│ │ └─────────────┘ │ │
│ └───────────────────┘ │
└─────────────────────────┘
.box {
width: 200px;
height: 100px;
padding: 20px; /* 内側余白 */
border: 2px solid black; /* 枠線 */
margin: 10px; /* 外側余白 */
}Flexboxは、柔軟なレイアウトを実現する強力なツールです。
.container {
display: flex;
justify-content: center; /* 水平方向の配置 */
align-items: center; /* 垂直方向の配置 */
gap: 20px; /* 要素間の間隔 */
}親要素(Container):
.flex-container {
display: flex;
flex-direction: row; /* row | column | row-reverse | column-reverse */
justify-content: center; /* flex-start | center | flex-end | space-between | space-around */
align-items: center; /* flex-start | center | flex-end | stretch */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
gap: 10px;
}子要素(Item):
.flex-item {
flex-grow: 1; /* 伸びる比率 */
flex-shrink: 1; /* 縮む比率 */
flex-basis: 200px; /* 基本サイズ */
}📸 スクリーンショット: Flexboxの動作イメージ図
Grid は、2次元レイアウトに最適です。
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3カラム */
grid-gap: 20px;
}例: カード型レイアウト
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
}画面サイズに応じてスタイルを変更します。
/* モバイル: デフォルト */
.container {
padding: 10px;
}
/* タブレット: 768px以上 */
@media (min-width: 768px) {
.container {
padding: 20px;
}
}
/* デスクトップ: 1024px以上 */
@media (min-width: 1024px) {
.container {
padding: 40px;
max-width: 1200px;
margin: 0 auto;
}
}- モバイルファースト: 小さい画面から設計
- 相対単位を使う: px ではなく rem, em, % を使用
- Flexbox/Gridを活用: float は古い手法
- 画像も可変に:
max-width: 100%
Next.jsプロジェクトでは、Tailwind CSSが標準で使えます。
ユーティリティファーストのCSSフレームワーク。クラス名でスタイルを指定します。
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<h1 className="text-4xl font-bold text-blue-600">
Hello Tailwind!
</h1>
</div>flex - display: flex
grid - display: grid
block - display: block
hidden - display: none
p-4 - padding: 1rem
px-6 - padding-left/right: 1.5rem
mt-8 - margin-top: 2rem
gap-4 - gap: 1rem
w-full - width: 100%
h-screen - height: 100vh
max-w-4xl - max-width: 56rem
text-xl - font-size: 1.25rem
font-bold - font-weight: 700
text-center - text-align: center
text-blue-600 - color: blue
bg-white - background: white
border - border: 1px solid
rounded-lg - border-radius: 0.5rem
shadow-md - box-shadow
md:flex - 768px以上で flex
lg:grid-cols-3 - 1024px以上で 3カラム
cd samples/02_html-css
npx create-next-app@latest profile-page
cd profile-page
npm run devsrc/app/page.tsx を以下のように編集します:
export default function Profile() {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 py-12 px-4">
<div className="max-w-4xl mx-auto">
{/* ヘッダーセクション */}
<header className="bg-white rounded-lg shadow-lg p-8 mb-8">
<div className="flex flex-col md:flex-row items-center gap-6">
<div className="w-32 h-32 bg-gradient-to-br from-blue-400 to-indigo-600 rounded-full flex items-center justify-center text-white text-4xl font-bold">
YT
</div>
<div className="text-center md:text-left">
<h1 className="text-3xl font-bold text-gray-800 mb-2">
山田 太郎
</h1>
<p className="text-xl text-gray-600">
Web Developer / Designer
</p>
</div>
</div>
</header>
{/* 自己紹介セクション */}
<section className="bg-white rounded-lg shadow-lg p-8 mb-8">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
自己紹介
</h2>
<p className="text-gray-700 leading-relaxed">
こんにちは!Web開発を学んでいる山田太郎です。
HTML、CSS、JavaScriptを使ったフロントエンド開発に興味があります。
現在はReactとNext.jsを勉強中で、
将来は自分のサービスを作りたいと考えています。
</p>
</section>
{/* スキルセクション */}
<section className="bg-white rounded-lg shadow-lg p-8 mb-8">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
スキル
</h2>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{['HTML', 'CSS', 'JavaScript', 'React', 'Next.js', 'Tailwind CSS'].map((skill) => (
<div
key={skill}
className="bg-blue-50 rounded-lg p-4 text-center font-semibold text-blue-700"
>
{skill}
</div>
))}
</div>
</section>
{/* 趣味セクション */}
<section className="bg-white rounded-lg shadow-lg p-8">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
趣味
</h2>
<ul className="space-y-2">
<li className="flex items-center gap-2">
<span className="text-blue-600">▪</span>
<span className="text-gray-700">プログラミング</span>
</li>
<li className="flex items-center gap-2">
<span className="text-blue-600">▪</span>
<span className="text-gray-700">読書(技術書中心)</span>
</li>
<li className="flex items-center gap-2">
<span className="text-blue-600">▪</span>
<span className="text-gray-700">映画鑑賞</span>
</li>
</ul>
</section>
</div>
</div>
)
}📸 スクリーンショット: 完成したプロフィールページ
プロフィールページに連絡先セクションを追加してください。
要件:
- メールアドレス
- GitHub URL
- Twitter/X URL
解答例
{/* 連絡先セクション */}
<section className="bg-white rounded-lg shadow-lg p-8 mt-8">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
連絡先
</h2>
<div className="space-y-3">
<div className="flex items-center gap-3">
<span className="font-semibold text-gray-600 w-24">Email:</span>
<a
href="mailto:yamada@example.com"
className="text-blue-600 hover:underline"
>
yamada@example.com
</a>
</div>
<div className="flex items-center gap-3">
<span className="font-semibold text-gray-600 w-24">GitHub:</span>
<a
href="https://github.com/yamada"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline"
>
github.com/yamada
</a>
</div>
<div className="flex items-center gap-3">
<span className="font-semibold text-gray-600 w-24">Twitter:</span>
<a
href="https://twitter.com/yamada"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline"
>
@yamada
</a>
</div>
</div>
</section>背景とカードの色をダークテーマに変更してみましょう。
ヒント: Tailwindの dark: プレフィックスを使います。
解答例
<div className="min-h-screen bg-gradient-to-br from-gray-900 to-gray-800 py-12 px-4">
<section className="bg-gray-800 rounded-lg shadow-lg p-8 mb-8">
<h2 className="text-2xl font-bold text-white mb-4">
自己紹介
</h2>
<p className="text-gray-300 leading-relaxed">
...
</p>
</section>
</div>原因: Tailwind CSSの設定が正しくない
解決策:
tailwind.config.tsでパスが正しいか確認
content: [
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],globals.cssに以下が含まれているか確認
@tailwind base;
@tailwind components;
@tailwind utilities;原因: Flexbox/Gridの設定ミス
解決策:
- ブラウザの開発者ツールでレイアウトを確認
display: flexやdisplay: gridが親要素に設定されているか確認
原因: メタタグが不足
解決策:
app/layout.tsx の <head> に以下を追加:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />原因: Next.jsの画像最適化の設定
解決策:
import Image from 'next/image'
<Image
src="/images/photo.jpg"
alt="プロフィール写真"
width={128}
height={128}
/>この章では以下のことを学びました:
- ✅ HTMLのセマンティックタグ
- ✅ CSSの基本とボックスモデル
- ✅ Flexbox・Gridレイアウト
- ✅ レスポンシブデザイン
- ✅ Tailwind CSSの活用
- ✅ 個人プロフィールページの作成
次の章では、JavaScriptを使った動的なUIについて学びます。
学習を完了したら、以下の項目をチェックしてください:
- ブラウザのレンダリングプロセス(DOM→CSSOM→Render Tree→Layout→Paint)を説明できる
- HTMLがページの構造を定義する役割を理解している
- CSSがページの見た目を制御する役割を理解している
- CSS Cascade(優先順位)の仕組みを理解している
- ボックスモデル(content, padding, border, margin)を理解している
- 基本的なHTML要素(h1-h6, p, div, span, a, img)を使える
- セマンティックHTML(header, nav, main, article, section, footer)を使える
- リストを作成できる(ul, ol, li)
- テーブルを作成できる(table, tr, th, td)
- フォーム要素(input, textarea, select, button)を使える
- CSSセレクタ(要素, class, id)を使い分けられる
- テキストスタイル(color, font-size, font-weight)を設定できる
- ボックスモデルプロパティを設定できる
- Flexboxで横並びレイアウトを作成できる
- CSS Gridでグリッドレイアウトを作成できる
- メディアクエリの構文を理解している
- モバイルファーストのアプローチを理解している
- ブレークポイントの概念を理解している
- レスポンシブな画像(max-width: 100%)を実装できる
- Tailwind CSSの利点(ユーティリティファースト)を理解している
- 基本的なユーティリティクラス(p-, m-, text-, bg-)を使える
- レスポンシブプレフィックス(sm:, md:, lg:)を使える
- Flexbox/Gridのユーティリティクラスを使える
- 簡単なプロフィールページを作成できる
- ブラウザの開発者ツールでHTML/CSSを検証できる
- CSSで要素を中央揃えできる
- ホバーエフェクトを実装できる
- HTMLとCSSだけではインタラクティブな機能を実現できないことを理解している
- JavaScriptが必要になる場面を理解している