はじめに:この記事を読むことで解決できる問題
PHPを中心に学習してきましたが、HTMLとCSSはいつも後回しにしていました。そのため、使うときもAIの出力したコードをそのまま使ったり、少し微調整を加える程度でした。
こんな悩みを抱えていませんか?
- HTMLでdivとspanばかり使ってしまう
- CSSでレイアウトが思うようにいかない
- コードが汚くなって後から修正するのが大変
お盆期間に、SB Create社が出版している「Webデザインの基本 きちんと入門」という参考書を読んだところ、ポイントを押さえることができ、理解が格段に深まりました。
この記事では、そこで学んだ知識のうち、HTMLとCSSを後回しにしてきた方が、基本的な仕組みを理解して効率的な開発ができるようになるポイントをまとめましたので、共有させていただきます。
第1部:HTML - 意味のあるマークアップの基礎
1-1. なぜセマンティクスが重要なのか
問題:divとspanを多用することの本当のリスク
多くの初心者は、見た目の調整が容易な<div>
や<span>
を多用しがちです。しかし、これらは構造的な意味を持たない「非セマンティック」要素であり、使用は「他の手立てがない場合」に限定すべきです。
なぜこれが問題なのか? 連鎖的な悪影響が発生します:
- アクセシビリティの低下:スクリーンリーダーがページの構造を正確に解釈できない
- SEOへの悪影響:検索エンジンがコンテンツの意味を理解しにくくなる
- 保守性の悪化:コードの意図が不明確になり、後の修正が困難になる
補足:WAI-ARIAについて
WAI-ARIAのrole
属性は、ネイティブなHTMLだけでは表現できない動的なUIの構造や状態を支援技術に伝えるための技術です。しかし「ARIAの第一のルール」として、必要なセマンティクスを持つネイティブHTML要素が存在する場合は、まずそれを使用するべきとされています。<div role="button">
ではなく<button>
要素を使うのが適切であり、安易にrole属性でネイティブ要素の意味を上書きすることは避けるべきです。
1-2. HTMLの基本構造とセマンティック要素
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>適切なセマンティック構造</title>
</head>
<body>
<header>
<h1>サイトのメインタイトル</h1>
<nav>
<ul>
<li><a href="#home">ホーム</a></li>
<li><a href="#about">私たちについて</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h2>記事のタイトル</h2>
<p>記事の内容...</p>
</article>
<aside>
<h3>関連情報</h3>
<p>サイドバーコンテンツ</p>
</aside>
</main>
<footer>
<p>© 2024 サイト名. All rights reserved.</p>
</footer>
</body>
</html>
1-3. セマンティック要素の正しい使い分け
要素名 | 使用する場面 | 避けるべき使い方 |
---|---|---|
<header> |
ページやセクションの導入部、ナビゲーション | 単なる装飾のためのコンテナ |
<nav> |
主要なナビゲーションリンク | 1つのリンクだけを含む場合 |
<main> |
ページの主要コンテンツ(1ページに1つ) | 複数配置する |
<article> |
独立して意味を成すコンテンツ | 単なる装飾的なグループ化 |
<section> |
関連するコンテンツのグループ(見出し必須) | 単なるスタイリングのため |
<aside> |
主要コンテンツに間接的に関連する補足情報 | メインコンテンツ |
<footer> |
セクションやページの末尾情報 | ページの途中での装飾 |
1-4. 見出し構造の重要性
見出しは、文書の論理的なアウトラインを形成します。
<!-- ❌ 悪い例:論理構造が破綻 -->
<h1>メインタイトル</h1>
<h3>なぜh2を飛ばす?</h3> <!-- h2がないのに h3 -->
<h2>逆順になってる</h2> <!-- h3の後に h2 -->
<!-- ✅ 良い例:論理的な構造 -->
<h1>メインタイトル</h1>
<h2>大見出し</h2>
<h3>中見出し</h3>
<h3>中見出し</h3>
<h2>大見出し</h2>
<h3>中見出し</h3>
1-5. コンテンツモデルによる要素の入れ子ルール
HTML5では「ブロック要素」「インライン要素」という区分が廃止され、コンテンツモデルという概念に変わりました。
カテゴリー名 | 役割 | 代表的な要素 | 含むことができる要素 |
---|---|---|---|
フローコンテンツ |
<body> 内の一般的な要素 |
div, p, img, a | ほとんどの要素 |
フレージングコンテンツ | テキストレベルのマークアップ | span, img, a, button | テキストや他のフレージング要素 |
セクショニングコンテンツ | 文書のアウトライン形成 | article, aside, nav, section | フローコンテンツ |
インタラクティブコンテンツ | ユーザー操作対象 | a, button, input | 他のインタラクティブ要素は不可 |
重要なルール例:
<!-- ❌ pタグの中にdivは入れられない -->
<p>
<div>これは無効</div>
</p>
<!-- ✅ 正しい入れ子 -->
<div>
<p>これは有効</p>
</div>
第2部:CSS - レイアウトとスタイリングの基礎
2-1. CSSセレクタの基本と詳細度の理解
CSSを書く上で避けて通れないのがセレクタです。適切なセレクタを選択することで、保守性が高く、パフォーマンスに優れたCSSを書くことができます。
基本セレクタの種類と使い分け
セレクタ | 記法 | 対象 | 詳細度 | 使用場面 |
---|---|---|---|---|
要素セレクタ | p |
指定した要素すべて | 低い | 基本スタイルの設定 |
クラスセレクタ | .class |
class属性を持つ要素 | 中程度 | 最も推奨(再利用可能) |
IDセレクタ | #id |
id属性を持つ要素(1つだけ) | 高い | ⚠️ 避けるべき(詳細度が高すぎる) |
属性セレクタ | [type="text"] |
指定した属性を持つ要素 | 中程度 | フォーム要素のスタイリング |
全称セレクタ | * |
すべての要素 | 最低 | リセットCSS |
<!-- HTML例 -->
<div class="card" id="main-card">
<h2 class="card__title">タイトル</h2>
<p class="card__text">本文テキスト</p>
<button class="button button--primary">ボタン</button>
<input type="email" required>
</div>
/* ✅ 良いセレクタの例 */
.card { } /* クラスセレクタ(推奨) */
.card__title { } /* BEM記法 */
.button--primary { } /* 状態の表現 */
[type="email"] { } /* 属性セレクタ */
/* ❌ 避けるべきセレクタの例 */
#main-card { } /* IDセレクタ(詳細度が高すぎ) */
div.card h2 { } /* 不必要な入れ子 */
.card .card__title { } /* 冗長な記述 */
セレクタの詳細度(Specificity)計算
CSSの適用優先順位は「詳細度」で決まります。詳細度は以下のように計算されます:
セレクタの種類 | 詳細度の重み | 計算方法 |
---|---|---|
インラインスタイル | 1000点 | style="color: red" |
IDセレクタ | 100点 |
#id 1つにつき +100 |
クラス・属性・疑似クラス | 10点 |
.class , [attr] , :hover 1つにつき +10 |
要素・疑似要素 | 1点 |
p , ::before 1つにつき +1 |
/* 詳細度の計算例 */
p /* 1点 (0,0,0,1) */
.text /* 10点 (0,0,1,0) */
p.text /* 11点 (0,0,1,1) */
#main .text /* 110点 (0,1,1,0) */
#main p.text /* 111点 (0,1,1,1) */
/* ❌ 問題のある例:詳細度が高すぎる */
#sidebar #menu .item a.link {
/* 詳細度: 231点 - 後から上書きが困難 */
color: blue;
}
/* ✅ 推奨:BEMで詳細度を低く保つ */
.menu__link {
/* 詳細度: 10点 - 上書きが容易 */
color: blue;
}
.menu__link--active {
/* 詳細度: 10点 - 同じレベルで管理 */
color: red;
}
結合子による要素の関係指定
結合子 | 記法 | 意味 | 例 |
---|---|---|---|
子結合子 | > |
直接の子要素のみ | .card > .title |
子孫結合子 |
(空白) |
すべての子孫要素 | .card .title |
隣接兄弟結合子 | + |
直後の兄弟要素 | h2 + p |
一般兄弟結合子 | ~ |
後続のすべての兄弟要素 | h2 ~ p |
疑似クラスと疑似要素
疑似クラス(:) - 要素の状態を表現
/* ユーザーインタラクション */
.button:hover { } /* マウスオーバー時 */
.button:focus { } /* フォーカス時 */
.button:active { } /* クリック時 */
/* 構造的疑似クラス */
li:first-child { } /* 最初の子要素 */
li:last-child { } /* 最後の子要素 */
li:nth-child(2n) { } /* 偶数番目の要素 */
疑似要素(::) - 存在しない要素を作成
/* コンテンツの前後に要素を追加 */
.quote::before {
content: '"';
font-size: 1.2em;
}
.quote::after {
content: '"';
font-size: 1.2em;
}
2-2. ボックスモデルの理解
問題:ボックスモデルの誤解によるレイアウト崩壊
多くの初心者が直面する問題は、width
とheight
の計算範囲の誤解です。
/* ❌ 問題のある例:content-box(デフォルト) */
.box {
width: 300px; /* コンテンツ領域のみ */
padding: 20px; /* 左右40px追加 */
border: 5px solid; /* 左右10px追加 */
/* 実際の幅 = 300 + 40 + 10 = 350px */
}
/* レスポンシブでは致命的 */
.container {
width: 50%; /* 親要素の50% */
padding: 20px; /* 親要素からはみ出る! */
}
解決策:border-boxによる直感的なレイアウト
/* ✅ 推奨:すべての要素にborder-boxを適用 */
*, *::before, *::after {
box-sizing: border-box;
}
.box {
width: 300px; /* padding + border込みで300px */
padding: 20px;
border: 5px solid;
/* 実際の幅 = 300px(変わらない) */
}
2-3. display プロパティによる要素の挙動
重要: width
、height
、margin
の効きかたはdisplay
で決まります。
display値 | 特徴 | width/height | margin | padding | 使用例 |
---|---|---|---|---|---|
block |
改行される、幅いっぱい | ✅ 設定可能 | ✅ 上下左右 | ✅ 上下左右 | div, p, h1 |
inline |
改行されない、テキスト流れ | ❌ 無効 | ❌ 上下無効 | ⚠️ 上下は重なる | span, a, img |
inline-block |
改行されない、ボックスは有効 | ✅ 設定可能 | ✅ 上下左右 | ✅ 上下左右 | button, input |
/* よくある間違いの修正例 */
/* ❌ インライン要素にwidth指定(無効) */
.inline-span {
width: 200px; /* 効かない */
}
/* ✅ inline-blockに変更 */
.inline-span {
display: inline-block;
width: 200px; /* 効く! */
}
2-4. モダンレイアウト:FlexboxとCSS Gridの適切な使い分け
判断基準:何次元のレイアウトか?
レイアウト手法 | 適用場面 | 具体例 | コード例 |
---|---|---|---|
Flexbox(1次元) | 一方向の配置・整列 | ナビゲーションメニュー、ボタングループ | .nav { display: flex; gap: 1rem; } |
CSS Grid(2次元) | 格子状の複雑なレイアウト | ページ全体の構造、カードグリッド | .grid { display: grid; grid-template-columns: repeat(3, 1fr); } |
<!-- Flexboxの例:ナビゲーション -->
<nav class="navigation">
<a href="#home">ホーム</a>
<a href="#about">概要</a>
<a href="#contact">お問い合わせ</a>
</nav>
<style>
.navigation {
display: flex;
gap: 2rem;
align-items: center; /* 縦方向中央揃え */
justify-content: center; /* 横方向中央揃え */
}
</style>
<!-- CSS Gridの例:ページレイアウト -->
<div class="page-layout">
<header>ヘッダー</header>
<nav>ナビゲーション</nav>
<main>メインコンテンツ</main>
<aside>サイドバー</aside>
<footer>フッター</footer>
</div>
<style>
.page-layout {
display: grid;
grid-template-areas:
"header header"
"nav main"
"sidebar main"
"footer footer";
grid-template-columns: 200px 1fr;
gap: 1rem;
}
header { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
aside { grid-area: sidebar; }
footer { grid-area: footer; }
</style>
第3部:CSS設計とパフォーマンス最適化
3-1. CSS設計:BEMによる保守性の向上
問題:安易な命名による技術負債
/* ❌ 保守性の低い例 */
.red-button { } /* 色が変わったら? */
.big-text { } /* サイズが変わったら? */
#content .item p { } /* 詳細度が高すぎる */
この問題は連鎖的に悪化します:
- スタイルの重複が発生
-
!important
の乱用 - CSSファイルの肥大化
- パフォーマンスの低下
解決策:BEM(Block, Element, Modifier)
/* ✅ BEMによる保守性の高い設計 */
/* Block:独立したコンポーネント */
.button { }
/* Element:ブロックを構成する要素 */
.button__icon { }
.button__text { }
/* Modifier:バリエーション */
.button--primary { }
.button--large { }
.button--disabled { }
<!-- HTMLでの使用例 -->
<button class="button button--primary button--large">
<span class="button__icon">📝</span>
<span class="button__text">保存する</span>
</button>
3-2. CSSプロパティの最適な記述順序
なぜ順序が重要? コードの可読性と保守性が劇的に向上します。
.component {
/* 1. レイアウト関連:要素の配置を決める */
display: flex;
position: relative;
top: 0;
left: 0;
z-index: 1;
/* 2. ボックスモデル:サイズと余白 */
width: 300px;
height: 200px;
margin: 1rem;
padding: 1rem;
box-sizing: border-box;
/* 3. 視覚的プロパティ:見た目の装飾 */
background-color: #f0f0f0;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
/* 4. タイポグラフィ:テキスト関連 */
font-family: 'Helvetica', sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 1.5;
text-align: left;
color: #333;
/* 5. その他:アニメーションなど */
transition: all 0.3s ease;
}
3-3. パフォーマンスを考慮した CSS 設計
セレクタのパフォーマンス
ブラウザは「右から左」にセレクタを評価するため、複雑な入れ子は避けるべきです。
/* ❌ パフォーマンス的に問題 */
.container .sidebar .widget ul li a {
/* ブラウザは a → li → ul → ... と逐次確認 */
}
/* ✅ BEMによる単一クラス(高速) */
.widget__link {
/* 直接マッチング可能 */
}
CSSの読み込み最適化
<!-- ❌ @importは避ける(直列読み込み) -->
<style>
@import url('styles.css');
@import url('layout.css');
</style>
<!-- ✅ linkタグで並列読み込み -->
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="layout.css">
まとめ:技術負債を防ぐ4つの原則
-
HTMLはセマンティックに: タグの意味を理解し、
<div>
の乱用を避ける - セレクタは詳細度を低く: クラスセレクタ中心、IDセレクタは避ける
- box-sizing: border-box を基本に: 直感的なレイアウト計算を可能にする
- FlexboxとCSS Gridを適切に使い分け: 1次元か2次元かで判断する
これらの原則は、単なる「きれいなコード」を書くためではなく、将来の技術負債を根本的に予防するための重要な投資です。
学んだ教訓
HTMLとCSSを後回しにしてきた私が最も驚いたのは、これらの基礎を理解することで、AIが生成したコードの意図がわかるようになったことです。コードをただ使うのではなく、「なぜこの構造なのか」を理解できるようになり、カスタマイズも格段に楽になりました。
基礎を学ぶことは遠回りに見えますが、実際には最も効率的な近道だったと実感しています。
さらに学びを深めるために:おすすめ参考書
この記事の内容は、以下の書籍を読んで理解した知識をもとに整理したものです:
「いちばんよくわかるWebデザインの基本きちんと入門[第2版]」
レイアウト/配色/写真/タイポグラフィ/最新テクニック
著:伊藤 庄平、益子 貴寛、宮田 優希、伊藤 由暁、久保 知己
なぜこの本をおすすめするのか
- 実践的で体系的: HTMLとCSSの基礎から、実際のWebサイト制作まで段階的に学べる
- 視覚的でわかりやすい: 図解やサンプルが豊富で、概念が理解しやすい
- 最新技術にも対応: FlexboxやCSS Gridなどのモダンな手法も詳しく解説
- デザインの視点も学べる: 技術だけでなく、レイアウトや配色といったデザインの基礎も習得できる
特にこんな方におすすめ
- プログラマーだけど、フロントエンドは苦手という方
- AIでコードは生成できるけど、なぜそうなるかわからないという方
- 基礎からしっかり学び直したいという方
- 独学で学習しているけど、体系的な知識が欲しいという方
この記事で紹介した内容は、同書のほんの一部です。より深く、より実践的な知識を身につけたい方は、ぜひ手に取ってみてください。きっと「なるほど、そういうことだったのか!」という発見がたくさんあるはずです。
Amazon商品ページ:いちばんよくわかるWebデザインの基本きちんと入門[第2版]
次のステップ: この記事の内容を実際に試して、さらに上記の参考書で学習を深めることで、HTMLとCSSの真の理解が得られるでしょう。ぜひあなた自身の学習体験も共有してください!