この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: HTMLへの埋め込み
SEOタイトル: HTML に JavaScript を埋め込む完全ガイド

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong><script></strong> タグでインライン記述、<strong><script src></strong> で外部ファイル読み込み</li><li><strong>defer</strong>: HTML パース完了後・DOMContentLoaded 前に順次実行(推奨)</li><li><strong>async</strong>: ダウンロード完了次第すぐ実行、順序保証なし(独立スクリプト向け)</li><li><strong>type="module"</strong>: ES Modules、<code>import/export</code> 使用可、自動で defer 相当</li><li>DOM 操作前には <strong>DOMContentLoaded</strong> イベントを待つ、innerHTML は XSS 対策必須</li></ul></td></tr></table>
<h2>JavaScript を HTML に埋め込む 3 つの方法</h2>

<h3>1. インライン (script タグ内に直接記述)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Sample&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1 id=&quot;title&quot;&gt;Hello&lt;/h1&gt;

    &lt;script&gt;
        // ここに JavaScript を直接書く
        document.getElementById(&apos;title&apos;).textContent = &apos;Hello, World!&apos;;
        console.log(&apos;inline script executed&apos;);
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3>2. 外部ファイル (推奨)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;!-- 同じディレクトリの app.js を読み込み --&gt;
&lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt;

&lt;!-- 絶対パス --&gt;
&lt;script src=&quot;/js/app.js&quot;&gt;&lt;/script&gt;

&lt;!-- CDN --&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/vue@3&quot;&gt;&lt;/script&gt;

&lt;!-- 整合性ハッシュ + crossorigin(推奨セキュリティ設定) --&gt;
&lt;script
  src=&quot;https://cdn.example.com/lib.js&quot;
  integrity=&quot;sha384-...&quot;
  crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;</code></pre>
<h3>3. インライン属性 (非推奨)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;!-- ❌ 非推奨(XSS リスク、CSP 違反、保守性低い) --&gt;
&lt;button onclick=&quot;alert(&apos;clicked&apos;)&quot;&gt;Click&lt;/button&gt;

&lt;!-- ✅ addEventListener 推奨 --&gt;
&lt;button id=&quot;btn&quot;&gt;Click&lt;/button&gt;
&lt;script&gt;
  document.getElementById(&apos;btn&apos;).addEventListener(&apos;click&apos;, () =&gt; {
    alert(&apos;clicked&apos;);
  });
&lt;/script&gt;</code></pre>
<h2>script タグの属性 (defer / async / type)</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>属性</th><th>ダウンロード</th><th>実行タイミング</th><th>順序</th><th>用途</th></tr></thead>
<tbody>
<tr><td>なし</td><td>同期、HTML パース停止</td><td>即時</td><td>HTML 内記述順</td><td>互換性、最終手段</td></tr>
<tr><td><code>defer</code></td><td>非同期</td><td>HTML パース完了後、DOMContentLoaded 前</td><td>HTML 内記述順</td><td>★通常のアプリスクリプト</td></tr>
<tr><td><code>async</code></td><td>非同期</td><td>ダウンロード完了次第</td><td>不定</td><td>独立した解析タグ等</td></tr>
<tr><td><code>type="module"</code></td><td>非同期</td><td>defer 相当</td><td>記述順</td><td>ES Modules</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;!-- ★推奨: head に defer 付きで読み込み --&gt;
    &lt;script src=&quot;app.js&quot; defer&gt;&lt;/script&gt;

    &lt;!-- 独立した広告/解析: async --&gt;
    &lt;script src=&quot;https://www.googletagmanager.com/gtag/js?id=GA_ID&quot; async&gt;&lt;/script&gt;

    &lt;!-- ES Modules: 自動で defer 動作 --&gt;
    &lt;script src=&quot;main.js&quot; type=&quot;module&quot;&gt;&lt;/script&gt;

    &lt;!-- 旧ブラウザフォールバック: module 非対応で読まれる --&gt;
    &lt;script src=&quot;main-legacy.js&quot; nomodule&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- body 末尾配置でも defer/async 不要だが、defer のほうが体感速い --&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2>ES Modules</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;!-- index.html --&gt;
&lt;script type=&quot;module&quot; src=&quot;main.js&quot;&gt;&lt;/script&gt;</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// main.js
import { greet } from &apos;./utils.js&apos;;   // 拡張子必須
greet(&apos;World&apos;);

// utils.js
export function greet(name) {
  console.log(`Hello, ${name}`);
}</code></pre>
<p>module は CORS / MIME (<code>application/javascript</code>) / 厳格モードが強制されるため、HTTP サーバ経由でアクセスする必要があります(<code>file://</code> 直接開きは不可)。</p>

<h2>DOM 操作の基本</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html">&lt;div id=&quot;app&quot;&gt;Hello&lt;/div&gt;
&lt;ul class=&quot;list&quot;&gt;
    &lt;li&gt;A&lt;/li&gt;
    &lt;li&gt;B&lt;/li&gt;
&lt;/ul&gt;

&lt;script&gt;
// 要素取得
const app = document.getElementById(&apos;app&apos;);
const items = document.querySelectorAll(&apos;.list li&apos;);
const first = document.querySelector(&apos;.list li:first-child&apos;);

// テキスト書き換え
app.textContent = &apos;World&apos;;

// HTML として埋め込み(XSS 注意)
app.innerHTML = &apos;&lt;strong&gt;Bold&lt;/strong&gt;&apos;;

// 属性
app.setAttribute(&apos;data-id&apos;, &apos;42&apos;);
app.dataset.id = &apos;42&apos;;

// クラス
app.classList.add(&apos;active&apos;);
app.classList.toggle(&apos;hidden&apos;);

// スタイル
app.style.color = &apos;red&apos;;

// イベント
app.addEventListener(&apos;click&apos;, (e) =&gt; {
  console.log(&apos;clicked&apos;, e.target);
});

// 子要素追加
const li = document.createElement(&apos;li&apos;);
li.textContent = &apos;C&apos;;
document.querySelector(&apos;.list&apos;).appendChild(li);
&lt;/script&gt;</code></pre>
<h2>innerText / textContent / innerHTML の違い</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>プロパティ</th><th>HTML タグ</th><th>非表示要素</th><th>パフォーマンス</th><th>XSS</th></tr></thead>
<tbody>
<tr><td><code>textContent</code></td><td>取得・設定とも文字列扱い(エスケープ済)</td><td>含む</td><td>★高速</td><td>安全</td></tr>
<tr><td><code>innerText</code></td><td>表示テキストのみ</td><td>含まない</td><td>遅い(レイアウト必要)</td><td>安全</td></tr>
<tr><td><code>innerHTML</code></td><td>HTML として解釈</td><td>含む</td><td>遅い(パース必要)</td><td>★危険</td></tr>
</tbody>
</table>

<h2>XSS (クロスサイトスクリプティング) 対策</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// ❌ 危険: ユーザー入力を innerHTML に直接
const userInput = &apos;<img src=x onerror="alert(1)">&apos;;
element.innerHTML = userInput;    // → スクリプト実行される

// ✅ textContent で文字列扱い
element.textContent = userInput;  // → "<img src=x..." と文字列表示

// ✅ どうしても HTML として描画したい場合は DOMPurify でサニタイズ
import DOMPurify from &apos;dompurify&apos;;
element.innerHTML = DOMPurify.sanitize(userInput);

// ✅ 自前エスケープ関数(簡易)
function escapeHtml(str) {
  return str.replace(/[&<>"&apos;]/g, m => ({
    &apos;&&apos;: &apos;&amp;&apos;, &apos;<&apos;: &apos;&lt;&apos;, &apos;>&apos;: &apos;&gt;&apos;, &apos;"&apos;: &apos;&quot;&apos;, "&apos;": &apos;&#39;&apos;
  }[m]));
}
element.innerHTML = escapeHtml(userInput);</code></pre>
<h2>DOMContentLoaded と load イベント</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>イベント</th><th>発火タイミング</th><th>用途</th></tr></thead>
<tbody>
<tr><td><code>DOMContentLoaded</code></td><td>HTML パース + defer スクリプト完了時</td><td>★ DOM 操作開始</td></tr>
<tr><td><code>load</code></td><td>画像/CSS/iframe 含め全リソース完了</td><td>サイズ計算等、画像確認</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">document.addEventListener(&apos;DOMContentLoaded&apos;, () =&gt; {
  // ここから安全に DOM 操作可能
  init();
});

window.addEventListener(&apos;load&apos;, () =&gt; {
  // 画像 size などの最終確認
});

// 既に発火済みかチェック
if (document.readyState === &apos;loading&apos;) {
  document.addEventListener(&apos;DOMContentLoaded&apos;, init);
} else {
  init();   // 既に発火後なら即実行
}</code></pre>
<h2>FAQ</h2>

<p><strong>Q: <code>defer</code> と body 末尾配置、どちらが良い?</strong><br />
A: 機能的にはほぼ同じですが、<code>defer</code> + head 配置のほうが「ダウンロードが HTML パースと並行して始まる」ぶん体感が速くなります。</p>

<p><strong>Q: <code>document.write</code> は?</strong><br />
A: 非推奨。HTML パース後に呼ぶとページ全体を破壊します。広告タグ等の互換目的以外は使わないこと。</p>

<p><strong>Q: jQuery の <code>$(function(){})</code> と <code>DOMContentLoaded</code> の違いは?</strong><br />
A: 同じです。jQuery 内部でも DOMContentLoaded を待つ実装になっています。</p>