HTMLはWebページの内容と意味を表すmarkup languageです。見た目はCSS、動作はJavaScriptへ分け、HTMLでは正しい要素と属性を選びます。
最頻出10項目
| やりたいこと | 最小形 |
|---|---|
| 文書を始める | <!doctype html> |
| 言語を指定 | <html lang="ja"> |
| 見出し | <h1>〜<h6> |
| 段落 | <p> |
| リンク | <a href="/about/">概要</a> |
| 画像 | <img src="/cat.jpg" alt="眠る猫"> |
| 箇条書き | <ul><li>項目</li></ul> |
| 意味のある区画 | <header>、<main>、<section> |
| 入力欄 | <label>と<input> |
| 送信 | <form>と<button type="submit"> |
文書の最小構造
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ページタイトル</title>
</head>
<body>
<header>サイト共通の見出し</header>
<main>
<h1>ページ固有の見出し</h1>
<p>本文です。</p>
</main>
<footer>フッター</footer>
</body>
</html>
titleはbrowser tabや検索結果の手がかりになります。lang="ja"は読み上げや翻訳の判断に使われます。通常、pageの主要内容は1つのmainへ入れます。
テキストと意味
<h1>記事タイトル</h1>
<h2>章タイトル</h2>
<p>
<strong>重要な内容</strong>と
<em>強調したい語句</em>です。
</p>
<blockquote cite="https://example.com/source">
引用文
</blockquote>
<p><code>npm run dev</code>を実行します。</p>
<pre><code>const answer = 42;</code></pre>
見出しlevelは文字サイズではなく文書構造で選びます。見た目を小さくしたい場合はCSSを使います。brを余白目的で並べず、paragraphはpへ分けます。
Link
<a href="/courses/">コース一覧</a>
<a href="https://example.com/">外部サイト</a>
<a href="mailto:info@example.com">メール</a>
<a href="#contact">お問い合わせへ</a>
新しいtabを開く必要がある場合だけtarget="_blank"を使います。
<a
href="https://example.com/"
target="_blank"
rel="noopener noreferrer"
>
外部サイト
</a>
「こちら」だけでなく、link先が分かる文言にします。buttonで行う操作をa href="#"で代用しません。
Image
<img
src="/images/classroom.webp"
alt="ノートPCで学習する受講生"
width="800"
height="450"
loading="lazy"
>
内容を伝える画像には目的を表すaltを書きます。装飾だけの画像はalt=""にします。widthとheightはlayout shiftを抑える手がかりになります。page上部の重要画像へ無条件にloading="lazy"を付けないでください。
List
<ul>
<li>順序のない項目</li>
<li>もう1つの項目</li>
</ul>
<ol>
<li>最初の手順</li>
<li>次の手順</li>
</ol>
<dl>
<dt>HTML</dt>
<dd>文書の構造を表す言語</dd>
</dl>
順番に意味がある手順はol、ない一覧はul、用語と説明はdlを使います。
Table
tableは表形式dataに使い、page layoutには使いません。
<table>
<caption>料金一覧</caption>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">月額</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">基本</th>
<td>15,000円</td>
</tr>
</tbody>
</table>
captionは表の目的、thとscopeはheaderとdataの関係を示します。横に広い表は小画面での表示方法もCSSで用意します。
Semantic structure
| 要素 | 主な用途 |
|---|---|
header | pageやsectionの導入 |
nav | 主要navigation |
main | pageの主要内容 |
article | 単独で成立する記事 |
section | 見出しを持つ意味上の区画 |
aside | 補足・関連内容 |
footer | pageやsectionのfooter |
address | article/pageの連絡先 |
<article>
<header>
<h2>HTMLの基本</h2>
<p><time datetime="2026-05-03">2026年5月3日</time></p>
</header>
<section>
<h3>文書構造</h3>
<p>本文です。</p>
</section>
</article>
見た目のgroup化だけならdivも適切です。すべてをsectionへ変える必要はありません。
Formの最小形
<form action="/contact" method="post">
<div>
<label for="name">名前</label>
<input
id="name"
name="name"
type="text"
autocomplete="name"
required
>
</div>
<div>
<label for="email">メールアドレス</label>
<input
id="email"
name="email"
type="email"
autocomplete="email"
required
>
</div>
<div>
<label for="message">お問い合わせ内容</label>
<textarea id="message" name="message" rows="6"></textarea>
</div>
<button type="submit">送信する</button>
</form>
label forとinputのidを同じにします。送信されるkeyはname属性です。placeholderをlabelの代わりにしません。
よく使うinput type
| type | 用途 |
|---|---|
text | 1行text |
email | email address |
password | password |
number | 数値 |
date | 日付 |
checkbox | 複数選択・同意 |
radio | 1つを選択 |
file | file |
hidden | 画面に出さない値 |
browser validationだけをserver側validationの代わりにしません。requestは改変できるため、serverでも型・長さ・権限を検証します。passwordやtokenをHTMLへ埋め込まないでください。
Group
<fieldset>
<legend>希望する連絡方法</legend>
<label>
<input type="radio" name="contact" value="email">
メール
</label>
<label>
<input type="radio" name="contact" value="phone">
電話
</label>
</fieldset>
関連するcontrolはfieldsetとlegendでまとめます。
Button
<button type="button">画面内の操作</button>
<button type="submit">フォーム送信</button>
<button type="reset">入力を初期化</button>
form内のbuttonは既定でsubmitになるため、送信しないbuttonにはtype="button"を明記します。
Global attributes
| 属性 | 用途 |
|---|---|
id | 文書内で一意の識別子 |
class | CSS・JS用の分類 |
hidden | 非表示 |
lang | 部分的な言語 |
dir | 文字方向 |
data-* | application固有data |
aria-* | accessibility情報の補足 |
ARIAでnative HTMLの意味を上書きする前に、目的に合うnative要素を選びます。click可能なdivよりbuttonを優先します。
よく使う補助要素
details
追加情報を開閉できます。JavaScriptなしでも操作できます。
<details>
<summary>受講に必要なもの</summary>
<p>インターネット接続とパソコンが必要です。</p>
</details>
summaryには、開いた先の内容が分かる文言を書きます。重要な注意を初期状態で隠す用途には向きません。
figure
画像・code・図とcaptionを1つのまとまりとして表します。
<figure>
<img
src="/images/network-flow.svg"
alt="ブラウザからサーバーまでの通信経路"
width="960"
height="540"
>
<figcaption>Webページが表示されるまでの流れ</figcaption>
</figure>
画像内の情報をaltだけで説明しきれない場合は、本文にも説明を書きます。
timeとaddress
<p>
公開日:
<time datetime="2026-05-03">2026年5月3日</time>
</p>
<address>
<a href="mailto:info@example.com">info@example.com</a>
</address>
datetimeにはmachine-readableな値を書きます。addressは任意の住所表示ではなく、直近のarticleまたはpageに関する連絡先に使います。
Form属性早見表
| 属性 | 意味 |
|---|---|
action | 送信先URL |
method | getまたはpost |
enctype | bodyのencoding |
autocomplete | browser補完 |
novalidate | browser validationを無効化 |
file uploadではmultipart/form-dataを使います。
<form
action="/upload"
method="post"
enctype="multipart/form-data"
>
<label for="document">提出ファイル</label>
<input
id="document"
name="document"
type="file"
accept=".pdf,image/png,image/jpeg"
>
<button type="submit">アップロード</button>
</form>
acceptはfile pickerの候補を絞る手がかりで、security validationではありません。serverで実体のformat、size、保存名、権限を検証します。
入力属性
| 属性 | 用途 |
|---|---|
required | 必須 |
minlength / maxlength | 文字数 |
min / max / step | 数値・日付範囲 |
pattern | 文字列pattern |
readonly | 変更不可・送信対象 |
disabled | 操作不可・通常送信されない |
autocomplete | 値の意味をbrowserへ伝える |
inputmode | mobile keyboardのhint |
<label for="postal-code">郵便番号</label>
<input
id="postal-code"
name="postal-code"
type="text"
inputmode="numeric"
autocomplete="postal-code"
pattern="[0-9]{7}"
>
errorは色だけで表さず、controlとの関係を文章で伝えます。
<label for="username">ユーザー名</label>
<input
id="username"
name="username"
aria-describedby="username-help username-error"
aria-invalid="true"
>
<p id="username-help">3文字以上で入力してください。</p>
<p id="username-error">入力が短すぎます。</p>
aria-invalidは実際にinvalidな状態で使います。初期表示からすべてerrorにしません。
Dialog
modal dialogにはdialogを利用できます。
<dialog id="confirm-dialog">
<h2>削除しますか?</h2>
<p>この操作は取り消せません。</p>
<form method="dialog">
<button value="cancel">キャンセル</button>
<button value="confirm">削除</button>
</form>
</dialog>
showModal()で開き、focusの移動、閉じた後のfocus復元、Escape操作を確認します。破壊的操作は明確な文言と確認を用意します。
Data属性とJavaScript
<button
type="button"
data-user-id="42"
data-action="open-profile"
>
プロフィールを開く
</button>
const button = document.querySelector("[data-action='open-profile']");
console.log(button?.dataset.userId);
data-*は公開してよいUI用dataに限ります。token、password、内部権限情報はHTMLへ埋め込まないでください。browser利用者はDOMを自由に閲覧・変更できます。
外部resource
<link rel="stylesheet" href="/styles/main.css">
<script type="module" src="/scripts/main.js"></script>
type="module"のscriptは既定でdefer相当です。第三者scriptはperformanceとsecurityへ影響するため、必要性、配信元、Content Security Policyを確認します。
iframeで外部contentを埋め込む場合は、titleと必要最小限のsandbox permissionを検討します。
<iframe
src="https://example.com/embed"
title="教材のプレビュー"
loading="lazy"
sandbox="allow-scripts"
></iframe>
必要性を確認せずallow-same-originやnavigation権限を追加しません。
最終チェック
htmlに正しいlangがあるtitleとh1がpage内容を表す- 見出しlevelが構造順になっている
- linkとbuttonを役割で使い分けている
- 画像の
altが目的に合う - form controlにlabelと
nameがある - keyboardだけで操作できる
- HTML validatorとbrowser開発toolでerrorを確認した
media、responsive image、OGPの詳しい設定は必要になった時点でMDNと各platformの公式資料を参照してください。