Skip to content

HTML チートシート

Web ページを作成するための標準マークアップ言語。

01

ドキュメント構造

基本ページテンプレート

すべての HTML5 ドキュメントは <!DOCTYPE html> で始まり、アクセシビリティと SEO のために lang 属性を持つ <html> が続きます。<head> にはメタデータ(charset、viewport、title)が含まれ、<body> には表示されるコンテンツが含まれます。viewport メタタグによりモバイルデバイスでの適切なレンダリングが保証されます。

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Web Page</title>
</head>
<body>
  <h1>Hello, World!</h1>
  <p>Welcome to my page.</p>
</body>
</html>

Head セクションとメタデータ

<head> 要素には機械可読なメタデータが含まれます。charset は文字エンコーディングを宣言し(UTF-8 はほぼすべての文字をカバー)、description メタタグは SEO に不可欠です — 検索エンジンが結果に表示します。HTML 解析後にスクリプトを読み込むには defer を使用してください。

html
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Page Title - Site Name</title>
  <meta name="description" content="A brief description for SEO">
  <meta name="author" content="John Doe">
  <link rel="stylesheet" href="style.css">
  <script src="app.js" defer></script>
</head>

コメントと条件付きコメント

HTML コメントは <!-- で始まり --> で終わります。ブラウザには表示されませんがページソースで見えます。コメントはメモ残し、セクションのマーク(TODO、FIXME)、ドキュメント化に便利です。条件付きコメント(IE 専用)は廃止されましたがレガシーコードに存在する可能性があります。

html
<!-- This is a single-line comment -->

<!--
  This is a
  multi-line comment
-->

<!-- TODO: Add form validation -->
<!-- FIXME: Fix layout on mobile -->

<!--[if lt IE 9]>
  <script src="html5shiv.js"></script>
<![endif]-->

見出しの階層

HTML には h1(最高位)から h6(最低位)までの 6 レベルの見出しがあります。レベルを飛ばさず階層順に使用してください。検索エンジンは見出しを使ってページ構造を理解します。ベストプラクティス:ページごとに h1 を 1 つ、主要セクションに h2、サブセクションに h3 など。

html
<h1>Main Page Title</h1>
<h2>Major Section</h2>
<h3>Subsection</h3>
<h4>Sub-subsection</h4>
<h5>Minor Heading</h5>
<h6>Lowest Level Heading</h6>

<!-- Use only one h1 per page for SEO -->
<h1>Blog Post Title</h1>
<h2>Introduction</h2>
<h3>Background</h3>

Div と Span コンテナ

<div> は要素をグループ化しスタイルを適用するブロックレベルコンテナです。<span> はテキストの一部をスタイルするインラインコンテナです。どちらも意味を持たない汎用要素です — アクセシビリティと SEO のため、適切な場合はセマンティックタグ(header、nav、main、article)を優先してください。

html
<div class="container">
  <div id="header" class="header">
    <span class="logo">MySite</span>
    <span class="tagline">Best Content</span>
  </div>
  <div class="content">
    <p>Main <span class="highlight">content</span> here.</p>
  </div>
</div>
02

テキストフォーマット

太字、イタリック、強調

<strong> は重要なテキストを示し(スクリーンリーダーが強調します)、<b> は純粋に視覚的な太字です。同様に <em> はストレス強調を示し(セマンティック)、<i> は視覚的なイタリックです。アクセシビリティには <strong> と <em> を優先してください。<b> と <i> はセマンティックな重要性なしのスタイル目的で許容されます。

html
<p>This is <strong>important</strong> text.</p>
<p>This is <b>bold</b> text.</p>
<p>This is <em>emphasized</em> text.</p>
<p>This is <i>italic</i> text.</p>
<p><strong>Warning:</strong> Do not touch!</p>

Mark、Delete、Insert

<mark> は関連性のあるテキストをハイライトします(検索ハイライトのように)。<del> は削除テキスト、<ins> は挿入テキストをマークし — 編集の表示に便利です。<s> は古い情報に取り消し線を引きます。<small> はサイドコメントや著作権用です。<u> はリンクに似るため慎重に使用してください。

html
<p>Please <mark>highlight this</mark> word.</p>
<p>The price is <del>$99</del> <ins>$79</ins> now.</p>
<p><s>Old information</s> is struck through.</p>
<p>Use <u>underline</u> sparingly.</p>
<p>Small <small>print</small> for side comments.</p>

上付き文字と下付き文字

<sub> は下付き文字(ベースラインより下)を作成し、化学式(H2O)や数学変数に使用します。<sup> は上付き文字(ベースラインより上)を作成し、指数(x²)、序数(1st)、脚注に使用します。どちらも垂直位置とフォントサイズを調整するインライン要素です。

html
<p>H<sub>2</sub>O is water.</p>
<p>E = mc<sup>2</sup> is Einstein's equation.</p>
<p>1st<sup>st</sup> January 2024</p>
<p>CO<sub>2</sub> emissions are rising.</p>
<p>x<sup>2</sup> + y<sup>2</sup> = r<sup>2</sup></p>

引用と出典

<blockquote> はブロックレベルの引用(インデント、複数行)用です。<q> はインラインの短い引用用です(引用符を自動的に追加)。cite 属性はソース URL を提供します。<cite> は作品のタイトルや著者名をタグ付けします。これらの要素は引用コンテンツのセマンティックマークアップを向上させます。

html
<blockquote cite="https://example.com/source">
  <p>The best way to predict the future is to invent it.</p>
  <footer>— <cite>Alan Kay</cite></footer>
</blockquote>

<p>As <q cite="https://example.com">someone once said</q>,
knowledge is power.</p>

コードと整形済みテキスト

<code> はインラインコードスニペット(等幅フォント)をマークします。<pre> は整形済みテキストの空白と改行を保持します。<pre><code> の組み合わせで適切なインデント付きのコードブロックを表示します。<kbd> はキーボード入力を表します。<samp> はプログラム出力用、<var> は数学式の変数用です。

html
<p>Use the <code>console.log()</code> function.</p>
<p>Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy.</p>

<pre><code>function hello() {
  console.log("Hello, World!");
  return true;
}</code></pre>

改行と水平線

<br> はテキスト内に改行を作成します(控えめに使用し、CSS を優先)。<hr> はセクション間の主題の区切りを表す水平線を作成します。<wbr> は長い単語や URL に改行機会を提案し、ブラウザが最適なポイントで改行できるようにします。間隔のための <br> の使用は避けてください — CSS マージンを使用してください。

html
<p>First line<br>Second line<br>Third line</p>

<p>Paragraph one.</p>
<hr>
<p>Paragraph two after a thematic break.</p>

<wbr><!-- word break opportunity for long URLs -->
https://example.com/<wbr>very<wbr>long<wbr>url
04

画像とマルチメディア

画像

アクセシビリティと SEO のために常に alt テキストを含めてください — スクリーンリーダーや画像読み込み失敗時に画像を説明します。loading='lazy' は画面外画像の読み込みを遅延し、ページ速度を向上させます。srcset と sizes はレスポンシブ画像を可能にします — ブラウザがデバイス解像度とビューポートに基づいて最適な画像を選択します。レイアウトシフトを防ぐため常に width と height を指定してください。

html
<!-- Basic image -->
<img src="photo.jpg" alt="A sunset over mountains" width="800" height="600">

<!-- Image with lazy loading -->
<img src="hero.jpg" alt="Hero banner" loading="lazy" decoding="async">

<!-- Responsive image with srcset -->
<img
  src="medium.jpg"
  srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
  sizes="(max-width: 600px) 480px, 800px"
  alt="Responsive photo"
>

Picture 要素

<picture> はアートディレクションとフォーマットフォールバックを提供します。<source> 要素は代替を提供し — ブラウザが最初にサポートするフォーマットを選びます(WebP/AVIF がより小さい)。media 属性は異なる画面サイズで異なる画像を可能にします。最後の <img> はフォールバックで常に存在する必要があります。これは完全に異なる画像を提供する場合に srcset より優れています。

html
<picture>
  <source srcset="webp-image.webp" type="image/webp">
  <source srcset="avif-image.avif" type="image/avif">
  <source srcset="wide.jpg" media="(min-width: 800px)">
  <img src="fallback.jpg" alt="Art-directed image">
</picture>

Audio

<audio> は音声コンテンツを埋め込みます。controls は再生/一時停止/音量コントロールを追加します。複数の <source> 要素でフォーマットフォールバックを提供します(MP3 が最も広くサポート)。autoplay はブラウザにより制限されます — ミュートされた自動再生は一般に許可されます。loop は音声を繰り返します。内側のテキストは音声がサポートされない場合に表示されます。ユーザー体験のために常にコントロールを提供してください。

html
<audio controls>
  <source src="song.mp3" type="audio/mpeg">
  <source src="song.ogg" type="audio/ogg">
  Your browser does not support the audio element.
</audio>

<!-- Autoplay (muted required in most browsers) -->
<audio autoplay muted loop>
  <source src="background.mp3" type="audio/mpeg">
</audio>

Video

<video> は再生、一時停止、音量、フルスクリーンのコントロール付きで動画を埋め込みます。poster は再生前のサムネイルを設定します。複数のソースでフォーマットフォールバックを提供します(MP4/H.264 が最も互換性あり)。<track> はアクセシビリティ用の字幕、キャプション、説明を追加します。playsinline は iOS での強制フルスクリーンを防ぎます。ミュート自動再生でない限り常にコントロールを含めてください。

html
<video controls width="640" height="360" poster="thumbnail.jpg">
  <source src="movie.mp4" type="video/mp4">
  <source src="movie.webm" type="video/webm">
  <track kind="subtitles" src="subs.vtt" srclang="en" label="English">
  Your browser does not support video.
</video>

<!-- Autoplay muted loop (common for backgrounds) -->
<video autoplay muted loop playsinline>
  <source src="bg.mp4" type="video/mp4">
</video>

Figure と Figcaption

<figure> は画像、図、コードリスト、引用などの自己完結型コンテンツとキャプションをグループ化します。<figcaption> はキャプションや凡例を提供します。このセマンティックグループ化はアクセシビリティを向上させます — スクリーンリーダーが関係をアナウンスします。フィギュアはテキストから参照でき(「図 1 を参照」)、コンテキストを失うことなくレイアウト内で移動できます。

html
<figure>
  <img src="chart.png" alt="Quarterly sales chart showing 20% growth">
  <figcaption>Figure 1: Q4 2024 sales growth by region.</figcaption>
</figure>

<figure>
  <blockquote>
    <p>The best way to predict the future is to invent it.</p>
  </blockquote>
  <figcaption>— Alan Kay, 1971</figcaption>
</figure>

Iframe 埋め込み

<iframe> は外部コンテンツ(動画、地図、他のページ)を埋め込みます。アクセシビリティのために常に title 属性を含めてください。loading='lazy' は画面外 iframe のパフォーマンスを向上させます。allow 属性は機能ポリシーを指定します。sandbox 属性はセキュリティのために iframe の機能を制限します。注意してください — iframe はパフォーマンスとセキュリティに影響を与える可能性があります。

html
<!-- Embed a YouTube video -->
<iframe
  src="https://www.youtube.com/embed/dQw4w9WgXcQ"
  width="560" height="315"
  title="YouTube video"
  frameborder="0"
  allow="accelerometer; autoplay; encrypted-media"
  allowfullscreen>
</iframe>

<!-- Embed a map -->
<iframe
  src="https://maps.google.com/maps?q=Paris&output=embed"
  title="Map of Paris" loading="lazy">
</iframe>
05

リスト

順序なしリスト

<ul> は順序なし(箇条書き)リストを作成します。各項目は <li> で囲みます。list-style-type CSS プロパティで箇条書きスタイルを変更します(disc、circle、square、none)。順序なしリストは順序が重要でない項目用です。ナビゲーションメニューや機能リストには list-style: none とカスタムスタイルを使用します。

html
<ul>
  <li>Apple</li>
  <li>Banana</li>
  <li>Cherry</li>
</ul>

<!-- Custom bullet style via CSS -->
<ul style="list-style-type: square;">
  <li>First item</li>
  <li>Second item</li>
</ul>

順序付きリスト

<ol> は順次項目用の順序付き(番号付き)リストを作成します。start 属性は開始番号を設定します。reversed は降順で項目を表示します。type 属性は番号スタイルを変更します(1、A、a、I、i)。ステップ、ランキング、順序が重要な任意のシーケンスに <ol> を使用します。

html
<ol>
  <li>First step</li>
  <li>Second step</li>
  <li>Third step</li>
</ol>

<!-- Start from a specific number -->
<ol start="5">
  <li>Fifth item</li>
  <li>Sixth item</li>
</ol>

<!-- Reverse order -->
<ol reversed>
  <li>Countdown 3</li>
  <li>Countdown 2</li>
  <li>Countdown 1</li>
</ol>

説明リスト

<dl> は用語(<dt>)と説明(<dd>)をペアにする説明リストを作成します。これは用語集、FAQ ページ、用語定義ペアに理想的です。複数の <dd> が 1 つの <dt> を説明でき、逆も可能です。説明リストは定義テーブルにはないセマンティックな意味を提供し、アクセシビリティを向上させます。

html
<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language</dd>

  <dt>CSS</dt>
  <dd>Cascading Style Sheets</dd>

  <dt>JavaScript</dt>
  <dd>A programming language for the web</dd>
</dl>

ネストされたリスト

<ul> や <ol> を <li> の中に配置してリストをネストできます。ブラウザはネストされたリストを自動的にインデントし、箇条書きスタイルを変更する場合があります。ネストは目次、ファイルツリー、マルチレベルメニューなどの階層構造を作成します。ユーザビリティのためネストを適度に(2-3 レベル)保ってください。深くネストされたリストは読みにくくなります。

html
<ul>
  <li>Fruits
    <ul>
      <li>Apple</li>
      <li>Banana</li>
    </ul>
  </li>
  <li>Vegetables
    <ol>
      <li>Carrot</li>
      <li>Spinach</li>
    </ol>
  </li>
</ul>

リンク付きリスト(ナビゲーション)

<nav> 内のリンクリストはセマンティックなナビゲーションメニューを作成します。ネストされた <ul> 要素はドロップダウンサブメニューを形成します。この構造はスクリーンリーダーにアクセス可能で CSS で簡単にスタイルできます。インタラクティブなドロップダウンには aria 属性(aria-expanded、aria-haspopup)を使用します。リストベースのナビゲーションはアクセシブルなメニューの標準パターンです。

html
<nav>
  <ul class="menu">
    <li><a href="/">Home</a></li>
    <li><a href="/products">Products</a>
      <ul class="submenu">
        <li><a href="/products/a">Product A</a></li>
        <li><a href="/products/b">Product B</a></li>
      </ul>
    </li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>
06

テーブル

基本テーブル

<table> は表形式データを作成します。<thead> はヘッダー行、<tbody> はボディ行、<tfoot> はフッター行をグループ化します。<tr> はテーブル行、<th> はヘッダーセル(太字、中央揃え)、<td> はデータセルです。thead/tbody/tfoot の使用はアクセシビリティを向上させ、より良いスタイリングを可能にします。テーブルはレイアウトではなくデータに使用してください。

html
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>City</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Alice</td>
      <td>30</td>
      <td>New York</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>25</td>
      <td>London</td>
    </tr>
  </tbody>
</table>

セルの結合

colspan はセルを複数列にまたがせます(水平にマージ)。rowspan はセルを複数行にまたがせます(垂直にマージ)。これらの属性は複数列をグループ化するヘッダーなどの複雑なテーブルレイアウトを作成します。結合には注意してください — スクリーンリーダーがテーブルを解析しにくくなる可能性があります。常にアクセシビリティをテストしてください。

html
<table border="1">
  <tr>
    <th colspan="2">Name</th>
    <th rowspan="2">Age</th>
  </tr>
  <tr>
    <th>First</th>
    <th>Last</th>
  </tr>
  <tr>
    <td>Alice</td>
    <td>Smith</td>
    <td>30</td>
  </tr>
</table>

テーブルキャプションとスコープ

<caption> はテーブルのタイトルを提供し、アクセシビリティを向上させます。<th> の scope 属性はヘッダーが列(scope='col')か行(scope='row')に適用されるかをスクリーンリーダーに伝えます。これは複雑なテーブルに不可欠です。さらに複雑なテーブルでは、id と headers 属性を使用してセルとヘッダーを明示的に関連付けます。

html
<table>
  <caption>Employee Salary Report 2024</caption>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Department</th>
      <th scope="col">Salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Alice</th>
      <td>Engineering</td>
      <td>$95,000</td>
    </tr>
  </tbody>
</table>

カラムグループ

<colgroup> はスタイリングのために列をグループ化します。その中の <col> 要素は特定の列にスタイル(特に幅)を適用します。これはすべてのセルに幅を設定するより効率的です。カラムグループは span 属性もサポートし、複数列を一度にスタイルできます。すべての行で一貫した列幅のために使用します。

html
<table>
  <colgroup>
    <col style="width: 30%;">
    <col style="width: 50%;">
    <col style="width: 20%;">
  </colgroup>
  <tr>
    <th>Product</th>
    <th>Description</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Laptop</td>
    <td>15-inch laptop</td>
    <td>$999</td>
  </tr>
</table>

テーブルのスタイリング

border-collapse: collapse は隣接する境界線を 1 つにマージします。:nth-child(even) でゼブラストライプ行を作成し(可読性を向上)、:hover でマウスオーバー時にハイライトします。th のスタイリングでヘッダーを区別します。テーブルスタイリングをクリーンで読みやすく保ちます — 過度な境界線を避けてください。レスポンシブテーブルは小さな画面でラッパーに overflow-x: auto が必要な場合があります。

html
<style>
  table { border-collapse: collapse; width: 100%; }
  th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
  th { background-color: #f4f4f4; }
  tr:nth-child(even) { background-color: #f9f9f9; }
  tr:hover { background-color: #e0e0e0; }
</style>
<table>
  <tr><th>Name</th><th>Score</th></tr>
  <tr><td>Alice</td><td>95</td></tr>
  <tr><td>Bob</td><td>87</td></tr>
</table>
07

フォームと入力

フォーム構造

<form> は入力コントロールを囲みます。action は送信 URL を指定し、method は GET(URL で表示)または POST(非表示)です。ファイルアップロードには enctype='multipart/form-data' が必要です。<fieldset> は関連フィールドをグループ化し、<legend> はキャプションを提供します。アクセシビリティのため、常に for/id マッチングで <label> と入力を関連付けてください。

html
<form action="/submit" method="POST" enctype="multipart/form-data">
  <fieldset>
    <legend>Personal Information</legend>

    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
  </fieldset>

  <button type="submit">Submit</button>
</form>

入力タイプ

HTML5 は組み込みのバリデーションとモバイルフレンドリーなキーボードを持つ多くの入力タイプを導入しました。type='email' はメール形式をバリデーションします。type='number' はスピナーを提供します。type='date' と 'time' はネイティブピッカーを表示します。type='color' はカラーピッカーを開きます。type='range' はスライダーを作成します。accept 付きの type='file' はファイルタイプを制限します。type='hidden' はユーザーに表示されないデータを格納します。

html
<input type="text" name="username" placeholder="Username">
<input type="email" name="email" required>
<input type="password" name="pwd" minlength="8">
<input type="number" name="age" min="0" max="120" step="1">
<input type="date" name="birthday">
<input type="time" name="appointment">
<input type="color" name="favcolor" value="#ff0000">
<input type="range" name="volume" min="0" max="100">
<input type="file" name="upload" accept="image/*">
<input type="hidden" name="token" value="abc123">

Select と Textarea

<select> はドロップダウンを作成します。<optgroup> はラベル付きで関連オプションをグループ化します。<option> は選択肢を定義し、selected 属性で 1 つを事前選択します。<textarea> は複数行テキスト入力用です。rows と cols は表示サイズを設定します。maxlength は文字数を制限します。placeholder はヒントを提供します。どちらも required と disabled 属性をサポートします。

html
<label for="country">Country:</label>
<select id="country" name="country">
  <optgroup label="North America">
    <option value="us">United States</option>
    <option value="ca">Canada</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="uk">United Kingdom</option>
    <option value="fr">France</option>
  </optgroup>
</select>

<label for="bio">Bio:</label>
<textarea id="bio" name="bio" rows="4" cols="40"
  maxlength="500" placeholder="Tell us about yourself"></textarea>

チェックボックスとラジオボタン

チェックボックスは複数選択を許可し、ラジオボタンは 1 つのみを許可します(同じ name を共有する場合)。checked 属性はオプションを事前選択します。クリック可能なテキストのために常に <label> で入力を囲んでください。アクセシビリティのために <fieldset> と <legend> で関連する選択肢をグループ化します。値は選択された場合のみサーバーに送信されます。

html
<fieldset>
  <legend>Select your interests:</legend>
  <label><input type="checkbox" name="interest" value="tech" checked> Tech</label>
  <label><input type="checkbox" name="interest" value="music"> Music</label>
  <label><input type="checkbox" name="interest" value="sports"> Sports</label>
</fieldset>

<fieldset>
  <legend>Choose a plan:</legend>
  <label><input type="radio" name="plan" value="free" checked> Free</label>
  <label><input type="radio" name="plan" value="pro"> Pro</label>
  <label><input type="radio" name="plan" value="enterprise"> Enterprise</label>
</fieldset>

フォームバリデーション

HTML5 は組み込みのクライアント側バリデーションを提供します。required は空の場合送信を防ぎます。minlength/maxlength はテキスト長を制約します。pattern はカスタムバリデーションに正規表現を使用します(title 属性でユーザーをガイド)。type='email' と type='url' は形式をバリデーションします。min/max は数値と日付で動作します。バリデーションを無効にするにはフォームに novalidate を追加します。

html
<form>
  <input type="text" name="username" required
         minlength="3" maxlength="20"
         pattern="[A-Za-z0-9_]+"
         title="3-20 alphanumeric characters">

  <input type="email" name="email" required>

  <input type="url" name="website"
         placeholder="https://example.com">

  <input type="number" name="age" min="18" max="99">

  <button type="submit">Submit</button>
</form>

ボタンと Datalist

type='submit' はフォームを送信し、type='reset' はすべてのフィールドをクリアし、type='button' はカスタムボタンです。<datalist> は <input> 要素にオートコンプリート候補を提供します — list/id でリンクします。<select> とは異なり、ユーザーはカスタム値を入力できます。これはテキスト入力の柔軟性と候補の便利さを組み合わせます。

html
<!-- Button types -->
<button type="submit">Submit Form</button>
<button type="reset">Reset</button>
<button type="button" onclick="alert('Hi')">Click Me</button>

<!-- Datalist for autocomplete suggestions -->
<label for="browser">Choose a browser:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
  <option value="Edge">
</datalist>
08

セマンティック HTML

Header とナビゲーション

<header> は導入コンテンツを表します — 典型的にはロゴ、見出し、ナビゲーションです。ページの上部または <article> や <section> 内に配置できます。<nav> はナビゲーションリンクを識別し、スクリーンリーダーがナビゲーションにスキップするのに役立ちます。ページは複数のヘッダーを持てます(例:セクションごとに 1 つ)。Header は head とは異なります — 表示されるコンテンツです。

html
<header>
  <h1>My Website</h1>
  <nav>
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/blog">Blog</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </nav>
</header>

Main と Article

<main> はページの主要コンテンツを囲みます(ページに 1 つのみ)。<article> は独立して配布できる自己完結型コンテンツ(ブログ記事、ニュース記事、フォーラム投稿)を表します。<time> と datetime は SEO のために機械可読な日付を提供します。<section> は見出しを持つ主題的に関連するコンテンツをグループ化します。これらのタグはドキュメントアウトラインとアクセシビリティを向上させます。

html
<main>
  <article>
    <h1>Blog Post Title</h1>
    <p>Published on <time datetime="2024-01-15">January 15, 2024</time></p>
    <p>The main content of the article...</p>
    <section>
      <h2>Subsection</h2>
      <p>More content...</p>
    </section>
  </article>
</main>

Section と Aside

<section> は見出しで関連コンテンツをグループ化します — コンテンツに自然な見出しがある場合に使用します。<aside> はメインコンテンツに付随的に関連するコンテンツ(サイドバー、プルクォート、広告、関連リンク)を表します。どちらもドキュメント構造を向上させます。セクションはネストできます。アサイドは通常サイドバーとしてスタイルされますが、セマンティックであり表現用ではありません。

html
<section>
  <h2>Services</h2>
  <p>We offer the following services:</p>
  <article>
    <h3>Web Design</h3>
    <p>Custom website design...</p>
  </article>
</section>

<aside>
  <h3>Related Articles</h3>
  <ul>
    <li><a href="/post1">Related Post 1</a></li>
    <li><a href="/post2">Related Post 2</a></li>
  </ul>
</aside>

Footer

<footer> はページまたはセクションのフッターコンテンツを含みます — 著作権、関連ドキュメントへのリンク、連絡先情報、サイトマップ。ページは複数のフッターを持てます(例:記事セクションごとに 1 つ)。フッターは視覚的に下部にある必要はありませんが、セマンティック的に終了コンテンツを表します。著作権記号には &copy; を使用します。

html
<footer>
  <div>
    <h3>About Us</h3>
    <p>Company information...</p>
  </div>
  <nav>
    <a href="/privacy">Privacy Policy</a>
    <a href="/terms">Terms of Service</a>
    <a href="/sitemap">Sitemap</a>
  </nav>
  <p>&copy; 2024 My Company. All rights reserved.</p>
</footer>

Details と Summary

<details> はインタラクティブな開示ウィジェットを作成します — ユーザーが <summary> をクリックするまでコンテンツは非表示です。open 属性はデフォルトで展開表示します。これはネイティブ HTML で JavaScript 不要です。FAQ、折りたたみ可能なセクション、プログレッシブディスクロージャーに最適です。ネストされた details でマルチレベルアコーディオンを作成します。[open] 属性セレクタでスタイルします。

html
<details>
  <summary>Click to expand FAQ</summary>
  <p>This content is hidden by default and shown when the summary is clicked.</p>
</details>

<!-- Open by default -->
<details open>
  <summary>What is HTML?</summary>
  <p>HTML (HyperText Markup Language) is the standard language for creating web pages.</p>
</details>

<!-- Nested details -->
<details>
  <summary>Advanced Topics</summary>
  <details>
    <summary>Sub-topic</summary>
    <p>Nested content...</p>
  </details>
</details>
09

メタタグと SEO

Charset と Viewport

charset='UTF-8' は文字エンコーディングを宣言し — すべての文字を正しく表示するために不可欠です。viewport メタタグはレスポンシブデザインに重要です:width=device-width はデバイス幅に一致し、initial-scale=1.0 はズームレベルを設定します。これがないとモバイルブラウザはデスクトップ幅でページをレンダリングします。これら 2 つのメタタグはすべての HTML ドキュメントに含めるべきです。

html
<head>
  <!-- Character encoding -->
  <meta charset="UTF-8">

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

  <!-- Internet Explorer compatibility -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>

Description と Keywords

description メタタグは SEO に最も重要です — 検索エンジンが結果のタイトル下に表示します(160 文字以内に保ってください)。keywords は現代の検索エンジンにほぼ無視されます。robots はインデックスを制御します:index/noindex、follow/nofollow。author はコンテンツ作成者をクレジットします。クリック率を向上させるために魅力的な説明を書いてください。

html
<meta name="description"
      content="Free HTML tutorials for beginners. Learn HTML tags, attributes, and semantic markup with examples.">

<meta name="keywords"
      content="HTML, tutorial, web development, markup">

<meta name="author" content="John Doe">
<meta name="robots" content="index, follow">

Open Graph(Facebook)

Open Graph(og:)メタタグは Facebook、LinkedIn、その他のプラットフォームで共有された時のページの表示を制御します。og:title、og:description、og:image、og:url が最も重要です。og:type は article、website、product などにできます。画像は少なくとも 1200x630 ピクセルにすべきです。デプロイ前に Facebook の Sharing Debugger でテストしてください。

html
<meta property="og:title" content="My Amazing Article">
<meta property="og:description" content="A brief description of the article.">
<meta property="og:image" content="https://example.com/image.jpg">
<meta property="og:url" content="https://example.com/article">
<meta property="og:type" content="article">
<meta property="og:site_name" content="My Website">
<meta property="og:locale" content="en_US">

Twitter Cards

Twitter Card メタタグは Twitter/X でのリンクの表示を制御します。twitter:card は summary、summary_large_image、player にできます。大きな画像カードが最もエンゲージングです。twitter:site と twitter:creator は Twitter アカウントにリンクします。Open Graph タグが存在する場合、Twitter はそれらにフォールバックしますが、明示的な Twitter タグでより制御できます。Twitter Card Validator でテストしてください。

html
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="My Amazing Article">
<meta name="twitter:description" content="A brief description.">
<meta name="twitter:image" content="https://example.com/image.jpg">
<meta name="twitter:site" content="@mywebsite">
<meta name="twitter:creator" content="@author">

Canonical と構造化データ

canonical リンクタグは検索エンジンにページの優先 URL を伝え、重複コンテンツのペナルティを防ぎます。JSON-LD 構造化データは検索エンジンがコンテンツを理解するのを助け、リッチスニペット(星評価、パンくずリスト、検索結果の FAQ アコーディオン)を可能にします。Article、Product、Event、FAQPage などの schema.org タイプを使用します。Google の Rich Results Test でバリデーションしてください。

html
<!-- Canonical URL (prevents duplicate content issues) -->
<link rel="canonical" href="https://example.com/article">

<!-- Structured data (JSON-LD) -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "My Article Title",
  "author": "John Doe",
  "datePublished": "2024-01-15",
  "image": "https://example.com/image.jpg"
}
</script>
10

SVG と Canvas

SVG の基礎

SVG(Scalable Vector Graphics)は品質を損なうことなくスケールする解像度非依存のグラフィックを作成します。インライン SVG は CSS でスタイル可能で JavaScript で操作可能です。一般的な図形:<circle>、<rect>、<line>、<ellipse>、<polygon>、<path>。SVG はアイコン、ロゴ、図に理想的です。ラスター画像とは異なり、SVG はあらゆるサイズで鮮明です。

html
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <circle cx="100" cy="100" r="50" fill="blue" stroke="black" stroke-width="2"/>
  <text x="100" y="105" text-anchor="middle" fill="white">Circle</text>
</svg>

<!-- Inline SVG (can be styled with CSS) -->
<svg width="100" height="100">
  <rect x="10" y="10" width="80" height="80" fill="red" rx="10"/>
</svg>

SVG 図形

SVG 図形は座標ベースの属性を使用します。<rect> は x、y、width、height が必要。rx/ry で角丸を作成します。<circle> は cx、cy(中心)と r(半径)が必要。<ellipse> は異なる x/y 半径に rx と ry を使用します。<line> は x1,y1 から x2,y2 に接続します。<polygon> は points リストを取ります。fill は内部の色、stroke は輪郭を設定します。

html
<svg width="300" height="200">
  <!-- Rectangle -->
  <rect x="10" y="10" width="80" height="50" fill="orange" rx="10" ry="10"/>

  <!-- Circle -->
  <circle cx="200" cy="50" r="40" fill="green"/>

  <!-- Ellipse -->
  <ellipse cx="100" cy="150" rx="60" ry="30" fill="purple"/>

  <!-- Line -->
  <line x1="10" y1="180" x2="290" y2="180" stroke="black" stroke-width="2"/>

  <!-- Polygon -->
  <polygon points="250,10 290,80 210,80" fill="pink"/>
</svg>

SVG パス

<path> は最も強力な SVG 要素で、d 属性とコマンドを使用します:M(moveto)、L(lineto)、H/V(水平/垂直線)、C(3次ベジェ)、Q(2次ベジェ)、A(円弧)、Z(パスを閉じる)。大文字 = 絶対座標、小文字 = 相対座標。viewBox は座標系を定義します。SVG アイコンはスケーラブルでスタイル可能なアイコンのためにパスを使用します。

html
<svg width="200" height="200">
  <!-- M=move, L=line, C=curve, Z=close -->
  <path d="M 10 10 L 100 10 L 100 100 Z" fill="none" stroke="black"/>

  <!-- Bezier curve -->
  <path d="M 10 100 C 50 10, 150 10, 190 100" fill="none" stroke="red"/>

  <!-- Arc -->
  <path d="M 10 100 A 90 90 0 0 1 190 100" fill="none" stroke="blue"/>
</svg>

<!-- SVG icon example -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
  <path d="M12 2L2 7v10l10 5 10-5V7z"/>
</svg>

Canvas の基礎

<canvas> は JavaScript で操作されるビットマップ描画サーフェスです。getContext('2d') で 2D コンテキストを取得します。SVG とは異なり、canvas はピクセルベース(スケーラブルでない)で DOM の一部ではありません。Canvas は複雑なアニメーション、ゲーム、画像処理に適しています。SVG は静的グラフィック、アイコン、インタラクティブチャートに適しています。ニーズに応じて選択してください。

html
<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
  const canvas = document.getElementById('myCanvas');
  const ctx = canvas.getContext('2d');

  // Draw a rectangle
  ctx.fillStyle = 'blue';
  ctx.fillRect(10, 10, 100, 80);

  // Draw a circle
  ctx.beginPath();
  ctx.arc(200, 50, 30, 0, Math.PI * 2);
  ctx.fillStyle = 'red';
  ctx.fill();

  // Draw text
  ctx.font = '20px Arial';
  ctx.fillText('Hello Canvas', 50, 150);
</script>

インライン SVG アイコン

SVG <symbol> は <use href='#id'> で参照される再利用可能なアイコンを定義します。これは SVG スプライト技法です — アイコンを一度定義し、どこでも使用します。symbol は非表示(display:none)で <use> でインスタンス化されます。アイコンは fill='currentColor' で CSS 'color' から色を継承します。このアプローチは効率的(1 つの定義で多数の使用)で完全にスタイル可能です。

html
<!-- Reusable SVG symbol -->
<svg style="display:none">
  <symbol id="icon-home" viewBox="0 0 24 24">
    <path d="M12 2L2 12h3v8h6v-6h2v6h6v-8h3z"/>
  </symbol>
</svg>

<!-- Use the icon -->
<svg width="24" height="24" fill="currentColor">
  <use href="#icon-home"/>
</svg>

<!-- Styled icon -->
<svg width="32" height="32" class="icon" style="color: blue;">
  <use href="#icon-home"/>
</svg>
11

アクセシビリティ(ARIA)

ARIA ロール

ARIA ロールは要素がスクリーンリーダーにとって何をするかを定義します。ランドマークロール(banner、navigation、main、complementary、contentinfo)はスクリーンリーダーユーザーがページ領域間をジャンプできるようにします。HTML5 セマンティック要素(<header>、<nav>、<main>)は暗黙的な ARIA ロールを持つため、role 属性の追加はしばしば冗長です — しかし古いブラウザには有用です。可能な場合は常に ARIA よりセマンティック HTML を優先してください。

html
<!-- Landmark roles for page structure -->
<header role="banner">Site Header</header>
<nav role="navigation">Main Menu</nav>
<main role="main">Primary Content</main>
<aside role="complementary">Sidebar</aside>
<footer role="contentinfo">Footer</footer>
<form role="search">Search Form</form>

<!-- Document structure roles -->
<article role="article">Blog Post</article>
<section role="region" aria-label="Comments">Comments</section>

aria-label と aria-labelledby

aria-label は可視ラベルが存在しない場合にアクセシブルな名前を定義します(例:アイコンのみのボタン)。aria-labelledby はコントロールにラベルを付ける可視テキスト要素の ID を参照します — 可視ラベルが画面に既にある場合に便利です。複数の ID がリストされる場合、テキストは順番に連結されます。可視テキストが存在する場合は aria-labelledby を優先してください。ラベルの同期を保てるためです。

html
<!-- aria-label provides accessible name directly -->
<button aria-label="Close menu" onclick="closeMenu()">✕</button>
<input type="search" aria-label="Search products" />

<!-- aria-labelledby references visible text -->
<div id="billing-label">Billing Address</div>
<input type="text" aria-labelledby="billing-label" />

<!-- Multiple labels combined -->
<span id="city">City</span>
<span id="required">required</span>
<input aria-labelledby="city required" />

aria-describedby とツールチップ

aria-describedby は要素 ID で要素を追加の説明テキストにリンクします。スクリーンリーダーはラベルの後にこの説明をアナウンスします。ヘルプテキスト、ヒント、エラーメッセージに理想的です。エラーメッセージに role='alert' を使用して、表示された時に即座にアナウンスされるようにします。エラーのあるフィールドに aria-invalid='true' を設定し、スクリーンリーダーが無効状態を示すようにします。

html
<label for="password">Password</label>
<input type="password" id="password"
       aria-describedby="pwd-help pwd-rules" />
<p id="pwd-help">Must be at least 8 characters</p>
<p id="pwd-rules">Include uppercase, number, and symbol</p>

<!-- Error messaging -->
<input type="email" id="email" aria-describedby="email-error" aria-invalid="true" />
<p id="email-error" role="alert">Please enter a valid email address</p>

ライブリージョン(aria-live)

ライブリージョンは動的コンテンツの変更をスクリーンリーダーユーザーにアナウンスします。aria-live='polite' はアナウンス前に一時停止を待ちます(ステータス更新に適しています)。aria-live='assertive' は即座に割り込みます(重大なエラー用)。aria-atomic='true' は変更部分のみではなくリージョン全体を読みます。aria-relevant はどの変更タイプ(追加、削除、テキスト)がアナウンスをトリガーするかを指定します。SPA、チャットアプリ、自動更新コンテンツに不可欠です。

html
<!-- Polite: announces when user is idle -->
<div aria-live="polite" id="status">Saving...</div>

<!-- Assertive: announces immediately, interrupts -->
<div aria-live="assertive" role="alert" id="errors">
  Connection lost!
</div>

<!-- aria-atomic reads entire region, not just changes -->
<div aria-live="polite" aria-atomic="true" id="cart">
  3 items in cart
</div>

<!-- aria-relevant controls what changes are announced -->
<div aria-live="polite" aria-relevant="additions text">
  Chat messages appear here
</div>

フォーカス管理と tabindex

tabindex はキーボードフォーカスの動作を制御します。tabindex='0' は非インタラクティブ要素(div、span)を自然な DOM 順序でフォーカス可能にします — カスタムウィジェットに使用します。tabindex='-1' は JS .focus() でプログラム的にのみフォーカス可能にします — モーダルやスキップターゲットに便利です。正の tabindex 値は自然なタブ順序を上書きし混乱を生むため使用しないでください。ページの最初のフォーカス可能要素として常にスキップリンクを提供してください。

html
<!-- tabindex="0": element is focusable in natural order -->
<div tabindex="0" role="button" onkeypress="handleKey()">
  Custom clickable div
</div>

<!-- tabindex="-1": focusable only via JS, removed from tab order -->
<div tabindex="-1" id="modal">Modal content</div>
<script>
  document.getElementById('modal').focus();
</script>

<!-- tabindex="1+": DO NOT USE — breaks natural tab order -->
<!-- Avoid: <div tabindex="2"> -->

<!-- Skip link for keyboard users -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<main id="main-content">...</main>

非表示コンテンツとスクリーンリーダー専用

aria-hidden='true' は要素をアクセシビリティツリーから削除しつつ可視のままにします — 装飾的アイコン、冗長なテキスト、画面外コンテンツに使用します。.sr-only パターンはテキストを視覚的に非表示にしつつスクリーンリーダーで読めるようにします — アイコンのみのボタンに不可欠です。フォーカス可能な要素に aria-hidden を使用しないでください。キーボードとスクリーンリーダーナビゲーション間の断絶を生むためです。clip 技法が最も堅牢な視覚的非表示メソッドです。

html
<!-- aria-hidden: visible but hidden from screen readers -->
<div aria-hidden="true">
  <i class="icon-decoration"></i> Decorative only
</div>

<!-- visually hidden but available to screen readers -->
<style>
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}
</style>
<button>
  <span class="sr-only">Delete item</span>
  <i class="icon-trash" aria-hidden="true"></i>
</button>
12

HTML5 API(Geolocation、Storage、Drag & Drop)

Geolocation API

Geolocation API はユーザーの物理的位置をリクエストできます。ブラウザは常に許可を求めます — ユーザーが明示的にアクセスを許可する必要があります。getCurrentPosition は成功とエラーコールバックに加えてオプションオブジェクト(enableHighAccuracy、timeout、maximumAge)を取ります。継続的トラッキングには watchPosition() を使用し、返される ID を clearWatch() に渡します。エラーを適切に処理してください(許可拒否、位置情報利用不可、タイムアウト)。Geolocation は現代のブラウザで HTTPS が必要です。

html
<!-- Request user location -->
<button onclick="getLocation()">Get My Location</button>
<p id="demo"></p>

<script>
function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        document.getElementById("demo").innerHTML =
          "Lat: " + pos.coords.latitude +
          "<br>Lon: " + pos.coords.longitude;
      },
      (err) => {
        alert("Error: " + err.message);
      },
      { enableHighAccuracy: true, timeout: 5000 }
    );
  } else {
    alert("Geolocation not supported.");
  }
}
</script>

Web Storage(localStorage と sessionStorage)

Web Storage はクライアントでキーと値のストレージを提供します。localStorage は無期限で保持し、sessionStorage はタブを閉じるとクリアされます。どちらも文字列のみ格納します — オブジェクトには JSON.stringify/parse を使用します。ストレージ制限はオリジンごとに約 5-10MB です。Cookie とは異なり、ストレージデータはすべての HTTP リクエストで送信されません。注意:ストレージは同期的でメインスレッドをブロックし、同じオリジンの任意のスクリプトがアクセス可能です(機密データには不適切)。

html
<!-- localStorage: persists until cleared -->
<script>
// Store data
localStorage.setItem("username", "alice");
localStorage.setItem("prefs", JSON.stringify({theme: "dark", lang: "en"}));

// Retrieve data
const user = localStorage.getItem("username");
const prefs = JSON.parse(localStorage.getItem("prefs") || "{}");

// Remove single item
localStorage.removeItem("username");

// Clear all items
localStorage.clear();

// sessionStorage: cleared when tab closes
sessionStorage.setItem("tempToken", "abc123");
</script>

Drag and Drop API

HTML5 Drag and Drop API はネイティブなドラッグインタラクションを可能にします。ソース要素に draggable='true' を設定します。ondragstart はドラッグ開始時に発生 — dataTransfer.setData() でドラッグデータを格納します。ドロップターゲットの ondragover はドロップを許可するために preventDefault() を呼び出す必要があります。ondrop が実際のドロップを処理します — dataTransfer.getData() でデータを取得します。OS からブラウザにファイルをドラッグするには event.dataTransfer.files を使用します。複雑なアプリには、より良いクロスブラウザサポートのために SortableJS のようなライブラリを検討してください。

html
<div id="drag1" draggable="true" ondragstart="drag(event)">
  Drag me!
</div>
<div id="dropzone" ondrop="drop(event)" ondragover="allowDrop(event)">
  Drop here
</div>

<script>
function allowDrop(ev) {
  ev.preventDefault(); // necessary to allow dropping
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  const data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
</script>

Page Visibility API

Page Visibility API はページがユーザーに可視かどうか(最小化されていない、バックグラウンドタブでない)を通知します。ユーザーが見ていない時に高コストなアニメーション、動画再生、ポーリングを一時停止するために使用します — バッテリーと CPU を節約します。document.hidden はブール値、document.visibilityState は 'visible'、'hidden'、'prerender' を返します。visibilitychange イベントが遷移時に発生します。これは実際の可視性検出に blur/focus より信頼性があります。

html
<script>
document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    console.log("Tab is hidden — pause video/animation");
    video.pause();
  } else {
    console.log("Tab is visible — resume");
    video.play();
  }
});

// Check current state
if (document.visibilityState === "visible") {
  console.log("Page is visible");
}
</script>

Fullscreen API

Fullscreen API は任意の要素をフルスクリーンモードで表示できます。requestFullscreen() はユーザージェスチャー(クリック/キー押下)でトリガーする必要があります。ブラウザによってはベンダープレフィックス(webkit、moz、ms)が必要な場合があります。fullscreenchange イベントがフルスクリーンへの入出力時に発生します。document.fullscreenElement は現在のフルスクリーン要素を参照します(フルスクリーンでない場合は null)。:fullscreen CSS 疑似クラスでフルスクリーン要素を異なるスタイルにします。

html
<button onclick="openFullscreen()">Fullscreen</button>
<button onclick="closeFullscreen()">Exit</button>
<div id="container">Content to fullscreen</div>

<script>
function openFullscreen() {
  const elem = document.getElementById("container");
  if (elem.requestFullscreen) {
    elem.requestFullscreen();
  } else if (elem.webkitRequestFullscreen) {
    elem.webkitRequestFullscreen();
  }
}

function closeFullscreen() {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  }
}

document.addEventListener("fullscreenchange", () => {
  console.log("Fullscreen:", !!document.fullscreenElement);
});
</script>
13

Web Components

Custom Elements

Custom Elements はカプセル化された動作を持つ再利用可能な HTML タグを作成できます。クラスは HTMLElement(または HTMLElement のサブクラス)を拡張します。connectedCallback は要素が DOM に追加された時に発生 — レンダリングに使用します。attributeChangedCallback は属性変更に反応しますが、observedAttributes にリストされた属性のみです。名前にはハイフンを含める必要があります(例:'my-greeting')— ネイティブ HTML との競合を避けるためです。customElements.define() で要素を登録します。スタイルカプセル化が必要な場合のみ Shadow DOM を使用してください。

html
<my-greeting name="World"></my-greeting>

<script>
class MyGreeting extends HTMLElement {
  constructor() {
    super();
    this.name = this.getAttribute("name") || "Guest";
  }
  connectedCallback() {
    this.innerHTML = `<h2>Hello, ${this.name}!</h2>`;
  }
  // Observe attribute changes
  static get observedAttributes() {
    return ["name"];
  }
  attributeChangedCallback(name, oldVal, newVal) {
    if (name === "name") {
      this.name = newVal;
      this.connectedCallback();
    }
  }
}
customElements.define("my-greeting", MyGreeting);
</script>

Shadow DOM

Shadow DOM はスタイルと DOM のカプセル化を提供します — シャドウツリー内のスタイルは漏出せず、ページスタイルも漏入しません。attachShadow({mode:'open'}) は element.shadowRoot でアクセス可能なシャドウルートを作成します。mode:'closed' は外部アクセスを拒否します(稀に使用)。<slot> 要素はライト DOM 子要素が投影されるプレースホルダーです。名前付きスロット(<slot name='title'>)は一致する slot 属性を持つ子要素にマッチします。::slotted() で投影コンテンツをスタイルします。Shadow DOM は自己完結型の再利用可能コンポーネント構築の鍵です。

html
<my-card>
  <span slot="title">Card Title</span>
  <p slot="body">Card content here.</p>
</my-card>

<script>
class MyCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: "open" });
    shadow.innerHTML = `
      <style>
        .card { border: 1px solid #ccc; padding: 16px; border-radius: 8px; }
        ::slotted([slot="title"]) { font-size: 1.5em; font-weight: bold; }
      </style>
      <div class="card">
        <slot name="title"></slot>
        <slot name="body"></slot>
      </div>
    `;
  }
}
customElements.define("my-card", MyCard);
</script>

HTML Templates

<template> 要素はページ読み込み時にレンダリングされない HTML を保持します — コンテンツは不活性です(スクリプトは実行されず、画像は読み込まれず、スタイルは適用されません)。.content(DocumentFragment)でコンテンツにアクセスし、cloneNode(true) でクローンしてインスタンス化します。テンプレートは JavaScript で生成される繰り返し構造に理想的です。innerHTML とは異なり、テンプレートは一度解析され、再解析なしで繰り返しクローンできます。Custom Elements と Shadow DOM と組み合わせて Web Components 標準を形成します。

html
<template id="row-template">
  <tr>
    <td class="name"></td>
    <td class="email"></td>
  </tr>
</template>

<script>
function addRow(name, email) {
  const template = document.getElementById("row-template");
  const clone = template.content.cloneNode(true);
  clone.querySelector(".name").textContent = name;
  clone.querySelector(".email").textContent = email;
  document.querySelector("tbody").appendChild(clone);
}

addRow("Alice", "[email protected]");
addRow("Bob", "[email protected]");
</script>

ライフサイクルコールバック

Custom Elements には 4 つのライフサイクルコールバックがあります。constructor() は要素作成時に実行されます(ここでの重い作業は避けてください)。connectedCallback() は DOM に追加された時に発生 — セットアップとレンダリングに理想的です。disconnectedCallback() は削除時に発生 — クリーンアップ(イベントリスナー、タイマー)に使用します。adoptedCallback() は adoptNode() で新しいドキュメントに移動された時に発生(稀)。attributeChangedCallback() は監視対象属性のみで発生します。アップグレード順序は常に:constructor → connectedCallback です。属性変更は connectedCallback の前に発生する可能性があります。

html
<script>
class LifecycleDemo extends HTMLElement {
  constructor() {
    super();
    console.log("1. constructor: element created");
  }
  connectedCallback() {
    console.log("2. connected: added to DOM");
  }
  disconnectedCallback() {
    console.log("3. disconnected: removed from DOM");
  }
  adoptedCallback() {
    console.log("4. adopted: moved to new document");
  }
  attributeChangedCallback(attr, oldVal, newVal) {
    console.log(`5. attribute '${attr}' changed: ${oldVal} -> ${newVal}`);
  }
  static get observedAttributes() {
    return ["data-status"];
  }
}
customElements.define("lifecycle-demo", LifecycleDemo);
</script>

Customized Built-in Elements

Customized built-in elements はネイティブ HTML 要素(button、input、div など)を拡張して組み込み動作を継承します。カスタムタグ名の代わりに 'is' 属性を使用します。customElements.define() の第 3 引数が拡張されるネイティブ要素を指定します。これは完全に新しい要素を作成するのではなく、既存の要素を強化する場合に便利です(例:<input> にバリデーションを追加)。注意:Safari は customized built-in elements をサポートしません — クロスブラウザ互換性のために autonomous custom elements を検討してください。

html
<!-- Extend a native button -->
<button is="my-button">Click me</button>

<script>
class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    this.addEventListener("click", () => {
      this.textContent = "Clicked!";
      this.style.background = "lightgreen";
    });
  }
  connectedCallback() {
    this.style.fontWeight = "bold";
  }
}
customElements.define("my-button", MyButton,
  { extends: "button" });
</script>
14

メディア要素(Audio と Video)

Video 要素

<video> 要素はプラグインなしで動画を埋め込みます。controls 属性は組み込みの再生/一時停止/音量コントロールを表示します。poster は再生前のプレビュー画像を指定します。複数の <source> タグでフォーマットフォールバックを提供します — ブラウザは最初にサポートするものを使用します(MP4/H.264 が最も広くサポート、WebM はオープンで効率的)。<track> 要素は WebVTT ファイルで字幕、キャプション、説明を追加します。非常に古いブラウザのためにフォールバックテキストを常に含めてください。自動再生には muted 属性を追加します — ほとんどのブラウザは音声付き自動再生をブロックします。

html
<video width="640" height="360" controls poster="preview.jpg">
  <source src="movie.mp4" type="video/mp4">
  <source src="movie.webm" type="video/webm">
  <track kind="subtitles" src="subs_en.vtt"
         srclang="en" label="English" default>
  <track kind="captions" src="caps_en.vtt"
         srclang="en" label="English Captions">
  Your browser does not support the video tag.
</video>

Audio 要素

<audio> 要素は音声を埋め込みます。controls は組み込みプレーヤー UI を表示します。controls がない場合、要素は不可視です — JavaScript(play()、pause()、volume、currentTime)で再生を制御します。preload='auto' はブラウザにファイルをバッファすべきことを示します。'metadata' は長さ/情報のみ読み込みます。'none' は再生まで何も読み込みません。MP3 は普遍的にサポートされます。OGG Vorbis はオープンですが Safari ではサポートされません。ゲームや精密なタイミングには、低レイテンシとエフェクトのために <audio> の代わりに Web Audio API を使用します。

html
<!-- Basic audio player -->
<audio controls>
  <source src="song.mp3" type="audio/mpeg">
  <source src="song.ogg" type="audio/ogg">
  Your browser does not support audio.
</audio>

<!-- Audio controlled by JavaScript -->
<audio id="player" src="song.mp3" preload="auto"></audio>
<button onclick="document.getElementById('player').play()">Play</button>
<button onclick="document.getElementById('player').pause()">Pause</button>
<button onclick="document.getElementById('player').volume += 0.1">Vol+</button>

Picture と srcset(レスポンシブ画像)

レスポンシブ画像は適切なサイズの画像を提供してパフォーマンスを向上させます。幅記述子(480w、800w)付きの srcset と sizes ヒントでブラウザが最適な画像を選びます — これは解像度切り替えに推奨されます。media クエリ付きの <picture> はアートディレクション(異なる画面で異なるクロップ)を可能にします。type 属性付きの <source> はモダンフォーマットフォールバック(WebP、AVIF)と JPG/PNG フォールバックを提供します。フォールバックとアクセシビリティのために <picture> の最後の子として常に通常の <img> を含めてください。

html
<!-- srcset: let browser choose resolution -->
<img src="small.jpg"
     srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
     sizes="(max-width: 600px) 480px, 800px"
     alt="Responsive image">

<!-- picture: art direction with different images -->
<picture>
  <source media="(max-width: 600px)" srcset="mobile.jpg">
  <source media="(max-width: 1200px)" srcset="tablet.jpg">
  <img src="desktop.jpg" alt="Art-directed image">
</picture>

<!-- Modern format with fallback -->
<picture>
  <source type="image/webp" srcset="photo.webp">
  <source type="image/avif" srcset="photo.avif">
  <img src="photo.jpg" alt="With format fallback">
</picture>

iframe 埋め込み

iframe は現在のページ内に別のドキュメントを埋め込みます。title 属性はアクセシビリティに不可欠です — スクリーンリーダーがアナウンスします。sandbox 属性はセキュリティのために iframe の機能を制限します:空の値はすべてをブロックし、トークン(allow-scripts、allow-forms、allow-same-origin)を追加して特定の機能を再有効化します。loading='lazy' はビューポート近くまで読み込みを遅延します。allow は機能ポリシー(camera、microphone、autoplay)を指定します。信頼できないコンテンツの埋め込みには注意してください — sandbox してください。クロスオリジン iframe は JavaScript でアクセスできません。

html
<!-- Basic iframe -->
<iframe src="https://example.com"
        width="600" height="400"
        title="Embedded Content">
</iframe>

<!-- Sandboxed iframe for security -->
<iframe src="untrusted.html"
        sandbox="allow-scripts allow-same-origin"
        loading="lazy">
</iframe>

<!-- YouTube embed -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
        allow="accelerometer; autoplay; encrypted-media"
        allowfullscreen
        title="YouTube video">
</iframe>

Embed と Object

<embed> と <object> は古い埋め込み方法で、主に <iframe> と <video> に置き換えられました。<embed> は自己完結型でシンプルですがフォールバックコンテンツを提供しません。<object> はより柔軟です — タグ内のコンテンツは埋め込みリソースが表示できない場合のフォールバックとして機能します。フォールバックが必要な PDF や SVG には <object> を使用します。現代の Web 開発では、外部ページには <iframe>、メディアには <video>/<audio>、ベクターグラフィックにはインライン <svg> を優先してください。<embed> は主にプラグインコンテンツ(Flash、現在は非推奨)に使用されます。

html
<!-- embed: simple, self-closing -->
<embed src="animation.svg" type="image/svg+xml"
       width="300" height="200">

<!-- object: more flexible with fallback -->
<object data="document.pdf" type="application/pdf"
        width="100%" height="600px">
  <p>Unable to display PDF.
     <a href="document.pdf">Download it instead.</a>
  </p>
</object>

<!-- embed YouTube without iframe -->
<embed src="https://www.youtube.com/v/VIDEO_ID"
       type="application/x-shockwave-flash"
       width="560" height="315">
15

入力タイプ詳細

日付と時刻入力

HTML5 の日付/時刻入力タイプは JavaScript ライブラリなしでネイティブピッカーを提供します。type='date' はカレンダー、type='time' はタイムピッカー、type='datetime-local' は両方を組み合わせます。type='month' と type='week' は月と週を選択します。min/max は選択可能範囲を制約します。step は粒度を定義します(例:30 分間隔で step='1800' 秒)。表示形式はブラウザ/ロケールにより異なりますが、送信される値は常に ISO 8601 形式(YYYY-MM-DD)です。すべてのブラウザがすべてのタイプを均等にサポートするわけではありません — クロスブラウザテストしてください。

html
<label for="birthday">Birthday:</label>
<input type="date" id="birthday" min="1900-01-01" max="2025-12-31">

<label for="appt">Appointment:</label>
<input type="time" id="appt" min="09:00" max="17:00" step="1800">

<label for="meeting">Meeting:</label>
<input type="datetime-local" id="meeting">

<label for="month">Pick a month:</label>
<input type="month" id="month">

<label for="week">Pick a week:</label>
<input type="week" id="week">

Number と Range 入力

type='number' は上下矢印付きのスピナーコントロールを提供します。min、max、step が値を制約します。通貨には step='0.01' を使用します。type='range' はスライダーをレンダリングします — 値がデフォルトで表示されないため、常に現在の値を表示する <output> または可視ラベルと併用してください。Number 入力は非数値入力をフィルタしますが一部の無効な文字を許可します。サーバー側でバリデーションしてください。スピナーが不要な数量には、inputmode='numeric' と pattern バリデーション付きの type='text' を検討してください。

html
<label for="qty">Quantity (1-100):</label>
<input type="number" id="qty" min="1" max="100"
       step="1" value="10">

<label for="price">Price ($):</label>
<input type="number" id="price" min="0" step="0.01"
       placeholder="0.00">

<label for="volume">Volume:</label>
<input type="range" id="volume" min="0" max="100"
       value="50" oninput="out.value=this.value">
<output id="out">50</output>

Color と File 入力

type='color' はネイティブカラーピッカーを開き、16 進数値(#rrggbb)を返します。type='file' はユーザーがファイルを選択できます。accept 属性は MIME タイプまたは拡張子でフィルタします(image/*、.pdf、image/png)。multiple 属性は複数ファイルの選択を許可します。JavaScript で files プロパティ(FileList)で選択されたファイルにアクセスします。画像のローカルプレビュー URL を作成するには URL.createObjectURL() を使用します。大きなファイルアップロードには、チャンクアップロードや進捗トラッキング用の File API を検討してください。常にサーバー側でファイルタイプとサイズをバリデーションしてください。

html
<label for="color">Pick a color:</label>
<input type="color" id="color" value="#ff0000">

<label for="avatar">Upload avatar:</label>
<input type="file" id="avatar" accept="image/*">

<label for="docs">Upload documents:</label>
<input type="file" id="docs" accept=".pdf,.doc,.docx" multiple>

<!-- File input with image preview -->
<input type="file" accept="image/*" onchange="preview(this)">
<img id="preview-img" hidden>
<script>
function preview(input) {
  const file = input.files[0];
  if (file) {
    document.getElementById("preview-img").src =
      URL.createObjectURL(file);
    document.getElementById("preview-img").hidden = false;
  }
}
</script>

datalist(入力候補)

<datalist> は入力フィールドにオートコンプリート候補を提供します。datalist の id にマッチする list 属性で入力にリンクします。<select> とは異なり、ユーザーは任意の値を入力できます — 候補は任意です。text、number、date、color、range 入力で動作します。ユーザーが入力するとブラウザが一致する候補を表示します。これはシンプルなユースケースで JavaScript オートコンプリートライブラリの軽量な代替です。注意:datalist 内のオプションのスタイリングはサポートされていません — ブラウザのデフォルトでレンダリングされます。

html
<label for="browser">Favorite browser:</label>
<input list="browsers" id="browser" name="browser">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
  <option value="Edge">
  <option value="Opera">
</datalist>

<!-- Works with various input types -->
<label for="color">Choose color:</label>
<input type="color" list="preset-colors" id="color">
<datalist id="preset-colors">
  <option value="#ff0000">
  <option value="#00ff00">
  <option value="#0000ff">
</datalist>

フォームバリデーション属性

HTML5 は属性で組み込みのクライアント側バリデーションを提供します。required は空の場合送信を防ぎます。type='email'/'url' は形式を自動的にバリデーションします。minlength/maxlength はテキスト長を制約します。min/max は数値と日付を制約します。pattern はカスタムバリデーションに正規表現を使用します。ブラウザはデフォルトのエラーバブルを表示します。setCustomValidity() でメッセージをカスタマイズします — ただし粘着エラーを避けるため入力時にクリアしてください(setCustomValidity(''))。クライアント側バリデーションは UX を向上させますが、バイパス可能なためセキュリティのためにサーバー側バリデーションと併用する必要があります。

html
<form>
  <label>Email: <input type="email" required></label>
  <label>Username:
    <input type="text" required minlength="3" maxlength="20"
           pattern="[a-zA-Z0-9_]+">
  </label>
  <label>Age:
    <input type="number" min="18" max="120" required>
  </label>
  <label>Website:
    <input type="url" placeholder="https://example.com">
  </label>
  <button type="submit">Submit</button>
</form>

<!-- Custom validation message -->
<input type="text" required
  oninvalid="this.setCustomValidity('Please enter your name')"
  oninput="this.setCustomValidity('')">
16

Service Worker と PWA

Service Worker 登録

Service Worker は Web ページとは別にバックグラウンドで実行される JavaScript ファイルで、オフラインサポート、プッシュ通知、バックグラウンド同期を可能にします。メインページから登録します — HTTPS で配信される必要があります。Service Worker ファイルの場所がスコープを決定します(そのディレクトリとサブディレクトリのページを制御)。登録は非同期でスコープごとに一度のみ発生します。初回訪問後、SW は後続のページ読み込みでアクティブ化します。ページがインタラクティブになるまで登録を遅延させるには load イベントを使用します。

html
<!-- Register a service worker in main page -->
<script>
if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/sw.js")
      .then((reg) => {
        console.log("SW registered:", reg.scope);
      })
      .catch((err) => {
        console.log("SW registration failed:", err);
      });
  });
}
</script>

Service Worker:キャッシュ

Service Worker ライフサイクルには 3 つのフェーズがあります:install(コアアセットをキャッシュ)、activate(古いキャッシュをクリーンアップ)、fetch(ネットワークリクエストをインターセプト)。ここに示す cache-first 戦略はキャッシュされたレスポンスを即座に提供し、ネットワークにフォールバックします。他の戦略には network-first(ネットワークを試行しキャッシュにフォールバック)と stale-while-revalidate(キャッシュを提供しバックグラウンドで更新)があります。キャッシュ更新をトリガーするには CACHE_NAME を更新します。Cache API は Request/Response ペアを格納します。Service Worker は必要な時のみ実行され、メモリ節約のためブラウザが終了できます。

html
// sw.js - Cache assets for offline use
const CACHE_NAME = "my-app-v1";
const ASSETS = ["/", "/index.html", "/style.css", "/app.js"];

// Install: cache core assets
self.addEventListener("install", (e) => {
  e.waitUntil(
    caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS))
  );
});

// Fetch: serve from cache, fall back to network
self.addEventListener("fetch", (e) => {
  e.respondWith(
    caches.match(e.request).then((cached) => {
      return cached || fetch(e.request);
    })
  );
});

// Activate: clean old caches
self.addEventListener("activate", (e) => {
  e.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(
        keys.filter((k) => k !== CACHE_NAME)
            .map((k) => caches.delete(k))
      )
    )
  );
});

Web App Manifest

Web App Manifest は Web アプリをインストール可能にする(ホーム画面に追加)JSON ファイルです。name はフルネーム、short_name はホーム画面アイコンに表示されます。display:'standalone' はブラウザ UI を非表示にしネイティブアプリのように見せます。theme_color はブラウザクロームの色に影響します。icons には少なくとも 192px と 512px サイズを含める必要があります。'purpose':'maskable' で Android が異なる形状にアイコンを適応できます。有効なマニフェストと登録された Service Worker が PWA の最小要件です。PWA コンプライアンスのために Lighthouse でテストしてください。

html
<!-- Link the manifest in HTML -->
<link rel="manifest" href="manifest.json">

<!-- manifest.json -->
{
  "name": "My PWA App",
  "short_name": "MyApp",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#1976d2",
  "orientation": "portrait",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

プッシュ通知

プッシュ通知はタブが閉じていてもユーザーを再エンゲージできます。まず Notification.requestPermission() で許可をリクエストします。次に PushManager でサブスクライブします — サブスクリプションオブジェクトにはエンドポイント URL とキーが含まれます。このサブスクリプションをサーバーに送信し、サーバーは Web Push API(認証用 VAPID キー付き)でプッシュメッセージを送信します。Service Worker の push イベントハンドラが通知を表示します。userVisibleOnly:true はすべてのプッシュが通知を表示する必要があることを意味します(サイレントプッシュなし)。HTTPS と Service Worker が必要です。

html
<!-- Request notification permission -->
<button onclick="subscribe()">Enable Notifications</button>

<script>
async function subscribe() {
  const permission = await Notification.requestPermission();
  if (permission !== "granted") return;

  const reg = await navigator.serviceWorker.ready;
  const subscription = await reg.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(VAPID_KEY)
  });
  // Send subscription to your server
  await fetch("/api/subscribe", {
    method: "POST",
    body: JSON.stringify(subscription)
  });
}
</script>

<!-- In sw.js: handle push events -->
self.addEventListener("push", (e) => {
  const data = e.data.json();
  e.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: "/icon-192.png",
      badge: "/badge.png"
    })
  );
});

バックグラウンド同期

Background Sync はユーザーが安定した接続を持つまでアクションを遅延できます。sync イベントを登録すると、接続が回復した時にブラウザが発火します — ユーザーがタブを閉じた場合でも。sync イベントハンドラ(Service Worker 内)が遅延作業を実行します。作業がエラーをスローした場合、ブラウザは指数バックオフで自動的に再試行します。e.tag は同期タイプを識別します — タグごとに 1 つの同期のみがキューに入ります。保留データの格納には IndexedDB を使用します。これはメッセージングアプリ、フォーム送信、データ同期に理想的です。Periodic Sync(定期更新用)は Chrome で利用可能ですがすべてのブラウザではありません。

html
// Register a sync event from the page
navigator.serviceWorker.ready.then((reg) => {
  return reg.sync.register("send-messages");
});

// Handle sync in sw.js
self.addEventListener("sync", (e) => {
  if (e.tag === "send-messages") {
    e.waitUntil(sendPendingMessages());
  }
});

async function sendPendingMessages() {
  const messages = await getMessagesFromIndexedDB();
  for (const msg of messages) {
    try {
      await fetch("/api/messages", {
        method: "POST",
        body: JSON.stringify(msg)
      });
      await deleteMessageFromIndexedDB(msg.id);
    } catch (err) {
      throw err; // triggers retry
    }
  }
}
17

メタタグ詳細(Open Graph と Twitter)

Open Graph タグ(Facebook)

Open Graph(OG)タグは Facebook、LinkedIn、ほとんどのソーシャルプラットフォームで共有された時のページの表示を制御します。og:title はヘッドライン、og:description は要約、og:image はプレビュー画像(推奨 1200x630px)です。og:type(website、article、video.movie)はレンダリングに影響します。記事の場合、より豊かなプレビューのために article:published_time、article:author、article:section を追加します。より高速なレンダリングのために常に og:image 寸法を指定してください。Facebook の Sharing Debugger でテストします。OG タグはソーシャルメディアマーケティングとクリック率に不可欠です。

html
<head>
  <meta property="og:title" content="My Awesome Article">
  <meta property="og:description" content="A deep dive into modern web development.">
  <meta property="og:type" content="article">
  <meta property="og:url" content="https://example.com/article">
  <meta property="og:image" content="https://example.com/img/og.jpg">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="630">
  <meta property="og:site_name" content="My Website">
  <meta property="og:locale" content="en_US">
  <meta property="article:published_time" content="2025-01-15T08:00:00Z">
  <meta property="article:author" content="Jane Doe">
</head>

Twitter Card タグ

Twitter Card タグは X(Twitter)でのリンクの表示を制御します。twitter:card タイプは 'summary'(小さい画像)、'summary_large_image'(テキスト上の大きな画像)、'player'(動画/音声)、'app' にできます。twitter:site はサイトの @ハンドル、twitter:creator は著者の @ハンドルです。画像は少なくとも 300x157px(summary)または 600x314px(大きな画像)にすべきです。twitter:image:alt はアクセシビリティを向上させます。Twitter の Card Validator でテストします。OG タグがあっても、Twitter 固有のタグを追加すると Twitter プレビューをより制御できます。

html
<head>
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@mywebsite">
  <meta name="twitter:creator" content="@janedoe">
  <meta name="twitter:title" content="My Awesome Article">
  <meta name="twitter:description" content="A deep dive into modern web dev.">
  <meta name="twitter:image" content="https://example.com/img/twitter.jpg">
  <meta name="twitter:image:alt" content="Article cover image">
</head>

Viewport とモバイルメタ

viewport メタタグはレスポンシブデザインに不可欠です — これがないとモバイルブラウザはデスクトップ幅でページをレンダリングしズームアウトします。width=device-width はデバイス幅に一致し、initial-scale=1 はズームレベルを設定します。ユーザーズームの無効化(user-scalable=no)は WCAG アクセシビリティガイドラインに違反するため避けてください。apple-mobile-web-app-capable は iOS ホーム画面に追加時にアプリをフルスクリーンにします。theme-color はモバイル Chrome と Safari のブラウザアドレスバーの色に影響します。これらのモバイル固有タグは PWA とモバイル体験を大幅に向上させます。

html
<head>
  <!-- Responsive viewport -->
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0">

  <!-- Disable zoom (accessibility concern — avoid) -->
  <meta name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

  <!-- iOS Safari: full-screen web app -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style"
        content="black-translucent">
  <meta name="apple-mobile-web-app-title" content="MyApp">

  <!-- Android Chrome theme color -->
  <meta name="theme-color" content="#1976d2">
</head>

HTTP-Equiv と Charset

http-equiv メタタグは HTML 内で直接 HTTP ヘッダーをシミュレートします。charset は <head> の最初の要素で、エンコーディングベースの XSS 攻撃を防ぐため最初の 1024 バイト以内にある必要があります。http-equiv='refresh' は遅延後にリダイレクトします — SEO のためにサーバー側リダイレクトを優先してください。メタ経由の Content-Security-Policy は制限があります(report-uri、frame-ancestors なし)— HTTP ヘッダーを優先してください。メタ経由の Cache-Control は信頼性が低いです — HTTP ヘッダーを使用してください。X-UA-Compatible は IE に最新のレンダリングエンジンを強制します。可能な場合は常に http-equiv より実際の HTTP ヘッダーを優先してください。

html
<head>
  <!-- Character encoding (must be first in head) -->
  <meta charset="UTF-8">

  <!-- Refresh/redirect after 5 seconds -->
  <meta http-equiv="refresh" content="5; url=https://example.com">

  <!-- Set content security policy -->
  <meta http-equiv="Content-Security-Policy"
        content="default-src 'self'; script-src 'self'">

  <!-- X-UA-Compatible for IE -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <!-- Cache control -->
  <meta http-equiv="Cache-Control"
        content="no-cache, no-store, must-revalidate">
</head>

構造化データ(JSON-LD)

JSON-LD(JavaScript Object Notation for Linked Data)は Google が推奨する構造化データフォーマットです。検索エンジンがコンテンツを理解するのを助け、検索結果でリッチスニペット(星評価、イベント日付、パンくずリスト、FAQ アコーディオン)を可能にします。一般的なタイプには Article、Product、Recipe、Event、LocalBusiness、FAQPage があります。type='application/ld+json' で <head> にスクリプトを配置します。Google の Rich Results Test でバリデーションしてください。構造化データはリッチスニペットを保証しませんが資格を与えます。検索結果からのクリック率を向上させる強力な SEO ツールです。

html
<head>
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "My Awesome Article",
    "author": {
      "@type": "Person",
      "name": "Jane Doe"
    },
    "datePublished": "2025-01-15",
    "image": "https://example.com/img/article.jpg",
    "publisher": {
      "@type": "Organization",
      "name": "My Website",
      "logo": {
        "@type": "ImageObject",
        "url": "https://example.com/logo.png"
      }
    }
  }
  </script>
</head>
18

セマンティック HTML 詳細

Article vs Section vs Div

適切なコンテナ要素の選択はアクセシビリティと SEO に重要です。<article> は独立して配布できるコンテンツ(ブログ記事、ニュース、コメント、商品カード)用です。<section> は主題的に関連するコンテンツをグループ化します — 常に見出しを持つべきです。<div> はセマンティック要素が適合しない場合のレイアウト/スタイリングの最後の手段です。ネストされた <article> 要素(投稿内のコメントなど)は有効です。経験則:コンテンツが RSS でシンジケート可能なら <article>、主題的な章なら <section>、純粋にレイアウト用なら <div> を使用します。

html
<!-- <article>: self-contained, syndicable content -->
<article>
  <h2>Blog Post Title</h2>
  <p>Content that makes sense on its own...</p>
  <article><h3>Comment 1</h3><p>...</p></article>
</article>

<!-- <section>: thematic grouping with a heading -->
<section>
  <h2>Chapter 1: Introduction</h2>
  <p>Related content...</p>
</section>

<!-- <div>: generic container, no semantic meaning -->
<div class="layout-wrapper">
  <div class="grid-item">Styling hook only</div>
</div>

Figure と Figcaption

<figure> はメインテキストから参照される自己完結型コンテンツ(画像、図、コードリスト、引用)を表します。<figcaption> はキャプション/タイトルを提供します。単なる <img> とは異なり、figure/figcaption は視覚要素とその説明をセマンティックにリンクします。スクリーンリーダーはフィギュアとキャプションをアナウンスします。フィギュアは参照するテキストに対して相対的に任意の場所に配置できます。番号で参照されるキャプション付きコンテンツ(図 1、リスト 1)には <figure> を使用します。純粋に装飾的な画像には空の alt を持つ単なる <img> を使用します。

html
<figure>
  <img src="chart.png" alt="Sales growth chart showing 40% increase">
  <figcaption>
    Figure 1: Quarterly sales growth from Q1 to Q4 2025.
    Data source: Internal sales database.
  </figcaption>
</figure>

<!-- Figure can contain code blocks too -->
<figure>
  <pre><code>const x = 42;</code></pre>
  <figcaption>Listing 1: Variable declaration example</figcaption>
</figure>

Details と Summary(開示)

<details> と <summary> は JavaScript なしでネイティブの折りたたみ可能(アコーディオン)セクションを作成します。<summary> をクリックするとコンテンツをトグルします。open 属性はデフォルトで展開表示します。toggle イベントは展開/折りたたみ時に発生します。これは FAQ、設定パネル、プログレッシブディスクロージャーに優れています。スクリーンリーダーは開示ウィジェットとしてアナウンスします。CSS でデフォルトの三角マーカーをスタイルできます(summary::-webkit-details-marker または list-style)。複雑なインタラクションには JavaScript が必要な場合がありますが、シンプルなトグルにはこのネイティブソリューションが理想的です。

html
<!-- Native collapsible without JavaScript -->
<details>
  <summary>Click to expand FAQ</summary>
  <p>Here is the hidden answer that appears when expanded.</p>
</details>

<!-- Open by default -->
<details open>
  <summary>Already expanded</summary>
  <p>This content is visible on page load.</p>
</details>

<!-- Nested disclosures -->
<details>
  <summary>Level 1</summary>
  <details>
    <summary>Level 2</summary>
    <p>Deeply nested content</p>
  </details>
</details>

Time と Mark 要素

<time> は機械可読な datetime 属性(ISO 8601 形式)を持つ人間可読な日付/時刻を囲みます。これは検索エンジン、カレンダー、支援技術が日付を正しく解析するのに役立ちます。datetime は日付(YYYY-MM-DD)、時刻(HH:MM)、タイムゾーン付き日時、期間(PT2H30M)をサポートします。<mark> は検索語の一致など関連性のためにハイライトされたテキストを表します。<strong> や <em>(重要性/強調を示す)とは異なり、<mark> はコンテキスト上の関連性を示します。両方の要素はセマンティックな意味と SEO を向上させます。

html
<!-- <time>: machine-readable dates/times -->
<p>Published on
  <time datetime="2025-01-15">January 15, 2025</time>
</p>
<p>Event at
  <time datetime="2025-03-20T14:30-05:00">2:30 PM EST</time>
</p>
<p>Duration:
  <time datetime="PT2H30M">2 hours 30 minutes</time>
</p>

<!-- <mark>: highlighted/relevant text -->
<p>Search results: the keyword
  <mark>HTML5</mark> appears in 3 documents.
</p>

Dialog 要素

<dialog> 要素はライブラリなしでネイティブのモーダルおよび非モーダルダイアログを提供します。showModal() はモーダルとして開き(バックドロップ付き、ページインタラクションをブロック)、show() は非モーダルで開きます。close() で閉じます。form method='dialog' は送信時にダイアログを閉じ、ボタンの値が returnValue になります。::backdrop 疑似要素でモーダルオーバーレイをスタイルします。ESC キーでモーダルダイアログを自動的に閉じます。トップレイヤーレンダリングにより、z-index に関わらずダイアログがすべてのコンテンツの上に表示されます。close イベントは閉じた後に発生します。これは現在よくサポートされ、多くの JavaScript モーダルライブラリを置き換えます。

html
<!-- Native modal dialog -->
<dialog id="myDialog">
  <h2>Confirm Action</h2>
  <p>Are you sure you want to proceed?</p>
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="confirm">Confirm</button>
  </form>
</dialog>

<button onclick="document.getElementById('myDialog').showModal()">
  Open Modal
</button>

<script>
const dialog = document.getElementById("myDialog");
dialog.addEventListener("close", () => {
  console.log("Dialog closed with:", dialog.returnValue);
});
// Close on backdrop click
dialog.addEventListener("click", (e) => {
  if (e.target === dialog) dialog.close();
});
</script>
19

高度なフォームと入力

Fieldset と Legend

<fieldset> は関連するフォームコントロールをグループ化し、<legend> はグループのキャプションを提供します。これはアクセシビリティに不可欠です — スクリーンリーダーはグループ内の各コントロールの前に legend をアナウンスし、コンテキストを提供します。fieldset の disabled 属性はその中のすべてのコントロールを無効にします。フィールドセットはデフォルトの境界線で視覚的な整理も向上させます。ラジオボタンの場合、fieldset/legend がグループにラベルを付ける推奨方法です。スクリーンリーダーユーザーを混乱させる可能性があるため、フィールドセットを深くネストしすぎないでください。

html
<form>
  <fieldset>
    <legend>Shipping Address</legend>
    <label>Street: <input type="text" name="street" required></label>
    <label>City: <input type="text" name="city" required></label>
    <label>ZIP: <input type="text" name="zip" pattern="[0-9]{5}"></label>
  </fieldset>

  <fieldset disabled>
    <legend>Billing (same as shipping)</legend>
    <label>Card: <input type="text" name="card"></label>
  </fieldset>

  <fieldset>
    <legend>Subscription Plan</legend>
    <label><input type="radio" name="plan" value="free"> Free</label>
    <label><input type="radio" name="plan" value="pro" checked> Pro</label>
  </fieldset>
</form>

Output と Progress 要素

<output> は計算結果を表示します — フォーム入力とのライブ関係(for 属性経由)を持ちます。計算値には span よりセマンティックに意味があります。<progress> はタスクの完了を表し(value/max)、値がない場合は不確定スピナーを表示します。<meter> は既知の範囲内のスカラー値(ディスク容量やテストスコアなど)を表します — low、high、optimum 属性が色(緑/黄/赤)に影響するしきい値を定義します。progress と meter はどちらもブラウザにより異なる組み込みスタイリングを持ちますが、CSS でカスタマイズできます。

html
<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="number" id="a" value="10"> +
  <input type="number" id="b" value="20"> =
  <output name="result" for="a b">30</output>
</form>

<!-- Progress bar -->
<label>Downloading: <progress id="prog" value="70" max="100">70%</progress></label>

<!-- Meter (gauge within a range) -->
<label>Disk usage: <meter value="0.6" min="0" max="1" low="0.5" high="0.8" optimum="0.2">60%</meter></label>
<label>Score: <meter value="85" min="0" max="100" low="40" high="70" optimum="90">85</meter></label>

フォームオートコンプリート

autocomplete 属性はブラウザが格納されたユーザーデータでフォームを入力するのに役立ちます。標準化されたトークンを使用します:'name'、'email'、'tel'、'street-address'、'address-level2'(市)、'postal-code'、'country'。クレジットカード用:'cc-name'、'cc-number'、'cc-exp'。autocomplete='off' はオートフィルを無効にします(ただしブラウザは非機密フィールドでこれを無視する場合があります)。autocomplete='one-time-code' はモバイルで SMS コードのオートフィルをトリガーします。適切な autocomplete トークンはフォーム完了率とユーザー体験を大幅に向上させます。パスワードマネージャーがフィールドを正しく識別するのにも役立ちます。

html
<form autocomplete="on">
  <!-- Browser can autofill name -->
  <label>Name: <input type="text" name="name" autocomplete="name"></label>

  <!-- Email autofill -->
  <label>Email: <input type="email" name="email" autocomplete="email"></label>

  <!-- Address autofill tokens -->
  <fieldset>
    <legend>Address</legend>
    <input autocomplete="street-address">
    <input autocomplete="address-level2"> <!-- City -->
    <input autocomplete="postal-code">
    <input autocomplete="country">
  </fieldset>

  <!-- Disable autocomplete for sensitive field -->
  <label>SSN: <input type="text" autocomplete="off"></label>

  <!-- One-time code (SMS) -->
  <label>Code: <input type="text" autocomplete="one-time-code"></label>
</form>

フォーム送信メソッド

GET はフォームデータを URL に追加します(可視、ブックマーク可能、長さ制限あり)— 検索やフィルターに使用します。POST はリクエストボディにデータを送信します(非表示、長さ制限なし)— データの作成/更新に使用します。ファイルアップロードには enctype='multipart/form-data' が必要です。ボタンの name/value ペアが送信に含まれます — 複数の送信ボタンが異なる値で同じ name を使用して異なるアクションをトリガーできます。AJAX 送信には FormData オブジェクトと fetch() を使用します。GET データはブラウザ履歴とサーバーログに表示されるため、機密データには常に POST を使用します。

html
<!-- GET: data in URL query string -->
<form method="GET" action="/search">
  <input name="q" value="html5">
  <!-- URL: /search?q=html5 -->
</form>

<!-- POST: data in request body -->
<form method="POST" action="/submit" enctype="application/x-www-form-urlencoded">
  <input name="name" value="Alice">
</form>

<!-- File upload: multipart -->
<form method="POST" action="/upload" enctype="multipart/form-data">
  <input type="file" name="document">
</form>

<!-- Form with custom submit button -->
<form method="POST" action="/save">
  <button type="submit" name="action" value="save">Save</button>
  <button type="submit" name="action" value="publish">Publish</button>
</form>

Contenteditable と Spellcheck

contenteditable='true' は任意の要素をブラウザで直接編集可能にします — リッチテキストエディタの基盤です。spellcheck='true' はブラウザのスペルチェックを有効にします(スペルミスに赤い下線)。コードスニペットには spellcheck='false' を設定して誤検出を避けてください。contenteditable 属性は継承できます — 'false' に設定されない限り子要素も編集可能です。編集可能コンテンツの保存には JavaScript が必要です(例:入力時に localStorage に格納)。contenteditable で本格的なリッチテキストエディタを構築するのは複雑です(ペースト、フォーマット、カーソル位置の処理)— 本番使用には Quill、TipTap、ProseMirror などのライブラリを検討してください。

html
<!-- Editable div -->
<div contenteditable="true">
  Click to edit this text directly in the browser.
</div>

<!-- Editable with spellcheck -->
<p contenteditable="true" spellcheck="true">
  Typoos will be underlined in red.
</p>

<!-- Turn off spellcheck for code -->
<pre contenteditable="true" spellcheck="false">
  const varible = "code"; // no spellcheck
</pre>

<!-- Entire document editable -->
<body contenteditable="true">

<!-- Save editable content -->
<div id="note" contenteditable="true"
     oninput="localStorage.setItem('note', this.innerHTML)">
  <script>document.getElementById('note').innerHTML =
    localStorage.getItem('note') || '';</script>
</div>
20

SEO メタタグ

Open Graph タグ

Open Graph タグ(Facebook が作成)はソーシャルメディアで共有された時のページの表示を制御します。og:image は 1200x630px にすべきです。これらのタグがないと、プラットフォームはページコンテンツからプレビューを推測し、多くの場合不適切になります。

html
<meta property="og:title" content="My Awesome Article">
<meta property="og:description" content="A deep dive into modern web design.">
<meta property="og:image" content="https://example.com/cover.jpg">
<meta property="og:url" content="https://example.com/article">
<meta property="og:type" content="article">
<meta property="og:site_name" content="Example Site">

Twitter Cards

Twitter Card タグは X/Twitter でのリンクのレンダリングを制御します。summary_large_image はタイトル上に目立つ画像を表示し、summary はより小さい正方形のサムネイルを表示します。twitter:site タグはカードをアカウントにリンクします。

html
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@yoursite">
<meta name="twitter:title" content="My Article">
<meta name="twitter:description" content="A deep dive into web design.">
<meta name="twitter:image" content="https://example.com/cover.jpg">

Canonical と Robots

rel="canonical" はマスター URL を指すことで重複コンテンツのペナルティを防ぎます。robots メタタグはクローラーを指示します:noindex はページを結果から削除し、nofollow はリンクフォローをブロックします。

html
<!-- Canonical: tells search engines the preferred URL -->
<link rel="canonical" href="https://example.com/article">

<!-- Robots: control indexing -->
<meta name="robots" content="index, follow">
<meta name="robots" content="noindex, nofollow">
<meta name="robots" content="noindex, follow">

構造化データ(JSON-LD)

JSON-LD 構造化データは検索エンジンがコンテンツを理解するのを助け、リッチ結果(星評価、パンくずリスト、イベント情報)を可能にします。Schema.org がボキャブラリーを定義します。script タグを head または body 内に配置します。

html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Modern Web Design",
  "author": { "@type": "Person", "name": "Jane Doe" },
  "datePublished": "2025-01-15",
  "image": "https://example.com/cover.jpg"
}
</script>

Meta Description と Viewport

description メタタグはクリック率に影響します — 160 文字以内に保ってください。viewport タグはモバイルのレスポンシブデザインに必須です。theme-color はブラウザ UI バーをスタイルします。charset は head の最初の要素である必要があります。

html
<meta name="description" content="A concise 150-160 character summary that appears in search results.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#4285f4">
<meta charset="UTF-8">
21

SVG の基礎

基本図形

SVG は XML 要素で描画します。図形には rect、circle、ellipse、line、polyline、polygon があります。ラスター画像とは異なり、SVG は品質を損なうことなくスケールし、CSS でスタイル可能です。fill は内部の色、stroke は輪郭を設定します。

html
<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="10" width="80" height="50" fill="steelblue"/>
  <circle cx="140" cy="40" r="30" fill="tomato"/>
  <line x1="10" y1="100" x2="180" y2="100" stroke="black" stroke-width="2"/>
  <ellipse cx="100" cy="120" rx="60" ry="20" fill="none" stroke="green"/>
</svg>

パス

path 要素は最も強力な SVG プリミティブです。コマンド:M(移動)、L(線)、H/V(水平/垂直)、C(3次ベジェ)、Q(2次)、A(円弧)、Z(閉じる)。大文字 = 絶対座標、小文字 = 相対座標。

html
<svg width="200" height="200">
  <!-- M=move, L=line, C=cubic bezier, Z=close -->
  <path d="M 10 10 L 100 10 L 100 100 Z" fill="none" stroke="black"/>
  <path d="M 10 150 C 50 50, 150 50, 190 150" stroke="red" fill="none"/>
  <path d="M 10 180 Q 100 120 190 180" stroke="blue" fill="none"/>
</svg>

グループと再利用

g で要素をグループ化して共有属性を適用したり一緒に変換します。defs 内に再利用可能な図形を定義し、use href="#id" で参照します。これにより SVG を DRY で小さく保ちます。

html
<svg width="200" height="200">
  <defs>
    <g id="star">
      <polygon points="50,5 61,39 98,39 68,61 79,95 50,75 21,95 32,61 2,39 39,39"/>
    </g>
  </defs>
  <use href="#star" x="0" y="0" fill="gold"/>
  <use href="#star" x="100" y="100" fill="orange"/>
</svg>

テキストとスタイリング

SVG テキストは実際のテキストです — 選択可能、検索可能、あらゆるスケールで鮮明です。font-family、font-size、font-weight は CSS と同じです。text-anchor は水平配置を制御します(start/middle/end)。

html
<svg width="300" height="100">
  <text x="10" y="50" font-family="Arial" font-size="24" fill="navy">
    Hello SVG
  </text>
  <text x="150" y="80" font-size="16" font-weight="bold" text-anchor="middle">
    Centered Bold Text
  </text>
</svg>

グラデーションとパターン

グラデーションは defs で定義し、fill="url(#id)" で参照します。linearGradient は線に沿って遷移し、radialGradient は中心点から放射します。各 stop がパーセンテージオフセットで色を定義します。

html
<svg width="200" height="100">
  <defs>
    <linearGradient id="lg" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="red"/>
      <stop offset="100%" stop-color="blue"/>
    </linearGradient>
    <radialGradient id="rg">
      <stop offset="0%" stop-color="yellow"/>
      <stop offset="100%" stop-color="green"/>
    </radialGradient>
  </defs>
  <rect width="100" height="100" fill="url(#lg)"/>
  <rect x="100" width="100" height="100" fill="url(#rg)"/>
</svg>
22

Canvas

図形の描画

Canvas API は 2D レンダリングコンテキスト経由で canvas 要素にピクセルを描画します。fillRect/strokeRect は矩形を描画し、パス(beginPath、arc、lineTo)は fill() や stroke() の前に複雑な図形を構築します。Canvas はラスターです — スケーリングすると描画がぼやけます。

html
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'tomato';
ctx.fillRect(10, 10, 100, 50);

ctx.strokeStyle = 'navy';
ctx.lineWidth = 3;
ctx.strokeRect(130, 10, 80, 80);

ctx.beginPath();
ctx.arc(200, 150, 40, 0, Math.PI * 2);
ctx.fill();

パスと線

パスはポイントごとに図形を構築します。moveTo は新しいサブパスを開始し、lineTo は直線セグメントを追加し、closePath は開始点に接続します。bezierCurveTo と quadraticCurveTo は制御点で曲線を描画します。

html
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(150, 50);
ctx.lineTo(100, 150);
ctx.closePath();
ctx.fillStyle = 'gold';
ctx.fill();
ctx.stroke();

// Bezier curves
ctx.beginPath();
ctx.moveTo(0, 200);
ctx.bezierCurveTo(100, 100, 200, 300, 300, 200);
ctx.stroke();

画像の描画

drawImage は画像、動画、別の canvas を描画します。9 引数形式はソース矩形をクロップしてデスティネーション矩形に描画します — スプライトシートに便利です。描画前に onload を待ってください。

html
const img = new Image();
img.src = 'photo.jpg';
img.onload = () => {
  ctx.drawImage(img, 0, 0);                    // full image
  ctx.drawImage(img, 0, 0, 200, 150);          // scaled
  ctx.drawImage(img, 50, 50, 100, 100, 300, 0, 100, 100); // cropped
};

アニメーションループ

requestAnimationFrame はブラウザの再描画ごとに draw() を 1 回スケジュールし(約 60fps)、タブが非表示の時に一時停止します。clearRect は各フレームで canvas をクリアして軌跡を防ぎます。物理には、一貫した速度のために移動にデルタタイムを掛けます。

html
let x = 0;
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = 'steelblue';
  ctx.fillRect(x, 50, 40, 40);
  x += 2;
  if (x > canvas.width) x = -40;
  requestAnimationFrame(draw);
}
requestAnimationFrame(draw);

ピクセル操作

getImageData は生の RGBA ピクセル値(チャネルごとに 0-255)の Uint8ClampedArray を返します。直接ピクセルアクセスでフィルターとエフェクトが可能です。putImageData は変更されたバッファを書き戻します。大きな canvas には遅いです。

html
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data; // RGBA bytes

for (let i = 0; i < data.length; i += 4) {
  const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
  data[i] = data[i + 1] = data[i + 2] = avg; // grayscale
}

ctx.putImageData(imageData, 0, 0);
23

Iframe と埋め込み

Iframe の基礎

iframe は現在のページ内に別のドキュメントを埋め込みます。アクセシビリティのために title 属性が必須です。loading="lazy" はビューポート近くまで読み込みを遅延します。レイアウトシフトを防ぐため常に width と height を設定してください。

html
<iframe
  src="https://example.com/widget"
  width="600"
  height="400"
  title="Example Widget"
  loading="lazy"
  referrerpolicy="no-referrer">
</iframe>

Sandbox 属性

sandbox 属性は iframe の機能を制限します。空の値はすべてをブロックします。トークンを追加して機能を再有効化します:allow-scripts、allow-forms、allow-same-origin、allow-popups。信頼できないコンテンツには allow-scripts と allow-same-origin を組み合わせないでください。

html
<!-- Locks down the iframe completely -->
<iframe src="untrusted.html" sandbox></iframe>

<!-- Selectively re-enable features -->
<iframe
  src="widget.html"
  sandbox="allow-scripts allow-same-origin allow-forms">
</iframe>

Embed と Object

embed と object はレガシー要素です。object はリソース失敗時に表示されるフォールバックコンテンツをサポートします。現代の HTML5 要素(video、audio、picture)が推奨されます。HTML コンテンツには iframe を、動画には video を使用してください。

html
<!-- Embed for plugins/media -->
<embed src="video.mp4" type="video/mp4" width="400" height="300">

<!-- Object with fallback content -->
<object data="report.pdf" type="application/pdf" width="100%" height="600">
  <p>Your browser cannot display PDFs. <a href="report.pdf">Download</a></p>
</object>

<!-- Video with multiple sources -->
<video controls>
  <source src="movie.webm" type="video/webm">
  <source src="movie.mp4" type="video/mp4">
  Your browser does not support video.
</video>

postMessage 通信

postMessage は iframe 境界(異なるオリジン)を越えて通信する唯一の方法です。第 3 引数で常にターゲットオリジンを指定してください。受信側では、メッセージを信頼する前に e.origin をバリデーションしてください。

html
<!-- Parent page -->
<iframe id="f" src="child.html"></iframe>
<script>
  const frame = document.getElementById('f');
  frame.contentWindow.postMessage({ type: 'greet', text: 'Hi' }, 'https://example.com');

  window.addEventListener('message', (e) => {
    if (e.origin !== 'https://example.com') return;
    console.log('From child:', e.data);
  });
</script>

レスポンシブ Iframe

iframe をレスポンシブにするには(例:16:9 動画)、アスペクト比パーセンテージ(16:9 で 56.25%)に等しい padding-bottom を持つコンテナで囲みます。iframe を絶対配置でコンテナを満たします。

html
<div style="position:relative; padding-bottom:56.25%; height:0; overflow:hidden;">
  <iframe
    src="https://youtube.com/embed/abc"
    style="position:absolute; top:0; left:0; width:100%; height:100%; border:0;"
    title="Video"
    allowfullscreen>
  </iframe>
</div>
24

パフォーマンス最適化

リソースヒント

リソースヒントはブラウザに必要前に接続を準備したりアセットをフェッチするよう指示します。preconnect は DNS/TCP/TLS をウォームアップします。preload は現在のページの重要なアセットを早期にフェッチします。prefetch はアイドル時間中に次ページのリソースをフェッチします。

html
<!-- Preconnect to a third-party origin -->
<link rel="preconnect" href="https://fonts.googleapis.com">

<!-- DNS prefetch for lower-priority origins -->
<link rel="dns-prefetch" href="https://analytics.example.com">

<!-- Preload critical assets -->
<link rel="preload" href="hero.webp" as="image">
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>

<!-- Prefetch next page -->
<link rel="prefetch" href="/next-page.html">

画像の遅延読み込み

loading="lazy" はユーザーがスクロールして近づくまで画面外画像の読み込みを遅延します。レイアウトシフトを防ぐため常に width と height を設定してください。picture 要素はモダンフォーマット(WebP/AVIF)と JPG フォールバックを提供します。

html
<!-- Native lazy loading -->
<img src="photo.jpg" loading="lazy" width="800" height="600" alt="...">

<!-- Picture with responsive sources -->
<picture>
  <source srcset="small.webp" media="(max-width: 600px)" type="image/webp">
  <source srcset="large.webp" type="image/webp">
  <img src="large.jpg" loading="lazy" width="1200" height="800" alt="...">
</picture>

スクリプト読み込み戦略

属性なしではスクリプトは HTML 解析をブロックします。async は並行ダウンロードしますが準備完了時に即座に実行します — 順序は保証されません。defer は並行ダウンロードし DOM 解析後に順序通りに実行します — メインスクリプトに最適です。

html
<!-- Normal: blocks HTML parsing -->
<script src="app.js"></script>

<!-- Async: downloads in parallel, runs ASAP -->
<script src="analytics.js" async></script>

<!-- Defer: downloads in parallel, runs after HTML parse -->
<script src="app.js" defer></script>

<!-- Module scripts defer by default -->
<script type="module" src="app.mjs"></script>

クリティカル CSS

クリティカル CSS(ファーストビューのコンテンツに必要なスタイル)をインライン化するとレンダーブロッキング CSS リクエストを排除し、ファーストペイントを高速化します。残りの CSS は preload トリックで非同期読み込みします。Critical のようなツールがクリティカル CSS を自動抽出します。

html
<!-- Inline above-the-fold CSS in head -->
<head>
  <style>
    body { margin: 0; font-family: sans-serif; }
    .hero { height: 100vh; background: #f0f0f0; }
  </style>
  <!-- Load the rest asynchronously -->
  <link rel="preload" href="full.css" as="style" onload="this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="full.css"></noscript>
</head>

パフォーマンスの測定

Performance API は実際のユーザータイミングを測定します。主要メトリクス:FCP(First Contentful Paint)、LCP(Largest Contentful Paint)、CLS(Cumulative Layout Shift)、INP(Interaction to Next Paint)。ラボデータには Lighthouse を使用します。

html
// PerformanceObserver for Core Web Vitals
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(entry.name, entry.startTime);
  }
}).observe({ entryTypes: ['paint', 'largest-contentful-paint'] });

// Navigation timing
const [nav] = performance.getEntriesByType('navigation');
console.log('DOM Content Loaded:', nav.domContentLoadedEventEnd);
console.log('Load:', nav.loadEventEnd);
25

高度なフォーム

入力タイプ

HTML5 入力タイプは組み込みのバリデーションと UI を提供します。email/url は形式をバリデーションします。number/date はピッカーを提供します。color/range は特殊な UI を持ちます。accept はファイルタイプをフィルタします。ブラウザがバリデーションを自動的に処理します。

html
<input type="email" required>
<input type="url" placeholder="https://">
<input type="number" min="0" max="100" step="5">
<input type="date" min="2024-01-01">
<input type="color" value="#ff0000">
<input type="range" min="0" max="10">
<input type="file" accept="image/*">

フォームバリデーション

required は空の場合送信を防ぎます。minlength/maxlength は長さを制限します。pattern は正規表現バリデーションを使用します。ブラウザは送信を防ぎエラーを表示します。setCustomValidity と invalid イベントでカスタマイズします。

html
<form>
  <input type="text" required minlength="3" maxlength="20" pattern="[A-Za-z]+">
  <input type="email" required>
  <input type="submit" value="Submit">
</form>

Fieldset と Legend

fieldset は関連するフォームフィールドをグループ化します。legend はキャプションを提供します。fieldset の disabled はすべてのフィールドを無効にします。関連する入力をグループ化することでアクセシビリティを向上します。スクリーンリーダーが各フィールドの legend をアナウンスします。

html
<fieldset>
  <legend>Shipping Address</legend>
  <label>Street: <input type="text" name="street"></label>
  <label>City: <input type="text" name="city"></label>
</fieldset>
<fieldset disabled>
  <legend>Billing (disabled)</legend>
  <input type="text" name="billing">
</fieldset>

Datalist

datalist は入力にオートコンプリート候補を提供します。ユーザーは選択または自由に入力できます。select とは異なりカスタム値を許可します。list 属性が id で input を datalist にリンクします。検索やタグに便利です。

html
<label>Choose browser:
  <input list="browsers" name="browser">
</label>
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
</datalist>

Output 要素

output は計算結果を表示します。for 属性は入力 ID にリンクします。フォーム変更でライブ更新します。シンプルな計算に JavaScript 不要です。ライブリージョンとしてスクリーンリーダーにアクセス可能です。

html
<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="number" id="a" value="0"> +
  <input type="number" id="b" value="0"> =
  <output name="result" for="a b">0</output>
</form>
26

アクセシビリティ(a11y)

ARIA ラベル

aria-label は可視テキストのない要素にアクセシブルな名前を提供します。aria-expanded はトグル状態を示します。aria-controls は制御要素にリンクします。HTML セマンティクスが不十分な場合のみ ARIA を使用してください。

html
<button aria-label="Close menu" onclick="closeMenu()">
  <svg>...</svg>
</button>
<nav aria-label="Main navigation">...</nav>
<button aria-expanded="false" aria-controls="menu">Menu</button>

ランドマークロール

ランドマークロールはスクリーンリーダーユーザーのナビゲーションを助けます。ほとんどのセマンティック要素は暗黙的なロールを持ちます。必要な場合のみ明示的なロールを追加してください。form の role="search" が検索ランドマークを作成します。セマンティック要素とのロールの冗長性を避けてください。

html
<header role="banner">...</header>
<nav role="navigation">...</nav>
<main role="main">...</main>
<aside role="complementary">...</aside>
<footer role="contentinfo">...</footer>
<form role="search">...</form>

フォーカス管理

キーボードユーザーのためにフォーカスを管理します。モーダルを開く時、フォーカスを中に移動します。閉じる時、フォーカスをトリガーに戻します。tabindex="-1" で要素をプログラム的にフォーカス可能にします。代替なしにフォーカスアウトラインを削除しないでください。

html
<button id="open">Open</button>
<div id="modal" hidden>
  <button id="close">Close</button>
</div>
<script>
document.getElementById('open').onclick = () => {
  modal.hidden = false;
  document.getElementById('close').focus();
};
</script>

スキップリンク

スキップリンクはキーボードユーザーが繰り返しのナビゲーションをバイパスできるようにします。フォーカスされるまで視覚的に非表示です。href はメインコンテンツ ID を指します。アクセシビリティコンプライアンス(WCAG)に不可欠です。ナビゲーション効率を向上します。

html
<body>
  <a href="#main" class="skip-link">Skip to main content</a>
  <nav>...long navigation...</nav>
  <main id="main">...</main>
</body>
<style>
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 0; }
</style>

Alt テキスト

Alt テキストはスクリーンリーダーのために画像を説明します。空の alt="" は装飾的画像をマークします(無視される)。外観ではなくコンテンツと目的を説明します。複雑な画像には別の場所に長い説明を提供します。ツールチップに alt を使用しないでください(title を使用)。

html
<!-- Informative image -->
<img src="chart.png" alt="Bar chart showing 30% increase in sales">
<!-- Decorative image -->
<img src="spacer.gif" alt="">
<!-- Complex image -->
<img src="diagram.png" alt="Network topology" longdesc="diagram-desc.html">
27

よくある落とし穴

Alt テキストの欠落

Alt テキストの欠落はアクセシビリティを壊します。スクリーンリーダーはファイル名を読みます。「image」や「photo」は役立ちません。コンテンツと目的を説明してください。空の alt="" は装飾的画像をマークします。alt 属性を完全に省略しないでください。

html
<!-- BAD: no alt -->
<img src="photo.jpg">
<!-- BAD: unhelpful alt -->
<img src="photo.jpg" alt="image">
<!-- GOOD: descriptive alt -->
<img src="photo.jpg" alt="Team meeting in conference room">
<!-- Decorative: empty alt -->
<img src="border.png" alt="">

Div スープ

すべてに div を使用するとセマンティックな意味が失われます。スクリーンリーダーがナビゲートできません。SEO がコンテンツ構造を理解できません。セマンティック要素を使用してください:header、nav、main、article、section、aside、footer。セマンティック意図のないグループ化に div を予約してください。

html
<!-- BAD: div for everything -->
<div class="header">...</div>
<div class="nav">...</div>
<div class="article">...</div>
<!-- GOOD: semantic elements -->
<header>...</header>
<nav>...</nav>
<article>...</article>

インラインスタイル

インラインスタイルはコンテンツとプレゼンテーションを混ぜ、メンテナンスを困難にします。特異性が高く、スタイルシートを上書きします。キャッシュや再利用ができません。クラスと外部スタイルシートを使用してください。動的値のみインラインスタイルに予約します。

html
<!-- BAD: inline styles -->
<div style="color: red; font-size: 16px;">Text</div>
<!-- GOOD: external CSS -->
<div class="error">Text</div>
<link rel="stylesheet" href="styles.css">

Button vs Link

ボタンはアクションをトリガーします(保存、削除、トグル)。リンクは URL にナビゲートします。アクションにリンクを使用するとキーボードナビゲーション(Space vs Enter)とセマンティクスが壊れます。スクリーンリーダーは異なるアナウンスをします。フォーム送信を防ぐには type="button" を使用してください。

html
<!-- BAD: link for actions -->
<a href="#" onclick="save()">Save</a>
<!-- GOOD: button for actions -->
<button type="button" onclick="save()">Save</button>
<!-- Link for navigation -->
<a href="/about">About</a>

見出しの階層

見出しはドキュメントアウトラインを作成します。レベルを飛ばさないでください(h1 から h3)。ページごとに h1 を 1 つ使用します(メインタイトル)。スクリーンリーダーユーザーは見出しでナビゲートします。論理的な階層を維持してください。視覚スタイリングには見出しレベルではなく CSS を使用してください。

html
<!-- BAD: skip levels -->
<h1>Title</h1>
<h3>Subtitle</h3>  <!-- Skipped h2 -->
<!-- BAD: multiple h1 -->
<h1>Title</h1>
<h1>Another</h1>
<!-- GOOD: hierarchical -->
<h1>Main Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>

Was this helpful?

Learning path

Learn from scratch

Learn this language from the ground up with structured lessons.