【JavaScript】innerHTMLとは?初心者向けにわかりやすく解説

はじめに

JavaScriptを使ってWebページの内容を柔軟に書き換えられる方法はいくつかあります。
その中でも、比較的シンプルに要素の中身を変更できるのがinnerHTMLです。

HTMLを初めて触る方の場合、静的なマークアップでページを組んでいくことが多いかもしれません。
しかし、少し慣れてくると、「ボタンを押したらテキストが変わるようにしたい」「フォームに入力した内容をそのまま画面に表示したい」といった場面が出てきます。

そんなときに便利なのがinnerHTMLを使った方法です。
この記事では、innerHTMLとは何なのか、どのように使えばよいのか、また気をつけるべき点は何かなどについて詳しく見ていきます。

実務ではユーザーの入力を受け取って動的に画面を作る場合が多くあります。
innerHTMLを適切に使えるようになると、簡単なカスタムUIやちょっとした表示切り替えを実装する際にとても便利です。

この記事を読むとわかること

  • innerHTMLの概要と基本的な使い方
  • DOM操作の基礎知識とinnerHTMLが果たす役割
  • innerHTMLを使う際の注意点やセキュリティリスク
  • 実務でも役立つ具体的なコード例や応用的な活用方法
  • 他のDOM操作手法との違いメリット・デメリット

innerHTMLとは何か

innerHTMLとは、HTMLの要素が持つプロパティの一つです。
要素の中身、つまり子要素を含むHTMLの文字列を取得・変更できます。

初心者の皆さんの中には「DOM操作って何だろう」と感じる方もいるかもしれません。
DOMとはDocument Object Modelの略で、WebページのHTML構造をJavaScriptから扱いやすいオブジェクトとして表現したものです。
そしてinnerHTMLは、そのDOMの要素内にあるHTMLの「塊」を表す文字列を操作するときに使います。

例えば、あるHTML要素の内容をガラッと別のHTMLに置き換えたい場合、innerHTMLに新たな文字列を代入すればOKです。
具体例を挙げると、画面に表示されたテキストや画像タグなどを、一瞬で別の構造に切り替えることができます。
こうした柔軟性の高さから、簡単なUI変更やメッセージの出し分けなどに用いられています。

DOM操作の基本

JavaScriptでWebページの内容を操作するには、まずHTML要素を取得する必要があります。
例えばdocument.querySelector()document.getElementById()などを使い、ターゲットとなる要素を指定します。

取得した要素を通じて、innerHTMLや属性の値を変更したり、新しい子要素を追加したりといった操作が可能です。
DOMは木構造のように階層をなしており、親要素、子要素の関係が明確になっています。

このDOMという仕組みを理解すると、Webページを「JavaScriptのコード」で好きなようにコントロールできるようになります。
innerHTMLは、そうしたDOM操作の中でも特に「要素の中身を文字列で扱う」ための方法といえます。

innerHTMLの基本的な特徴

innerHTMLの最大の特徴は、HTMLタグを含んだ文字列を直接指定できるという点です。
テキストだけではなく、タグを入れ込んでレイアウトまでまとめて変更できるため、一括でUIを切り替えることが簡単にできます。

一方で、innerHTMLの文字列に直接HTMLやスクリプトタグを埋め込んでしまうと、意図しない挙動が起こる可能性があります。
例えばスクリプトを埋め込むと、その場でJavaScriptが実行されることもあるため、使い方には注意が必要です。

初心者の方は「文字列を操作するだけで見た目も全部変えられるのは楽ちん」と思うかもしれませんが、適切に利用しないとセキュリティリスクを生む場面があります。
後ほど詳しく説明しますが、特にユーザーが入力したデータをむやみにinnerHTMLで表示するのは控えたほうがよいケースが多いです。

innerHTMLの使い方

ここでは実際にinnerHTMLを使ったコード例を通して、その基本的な使い方を説明します。
初心者の皆さんでも理解できるように、できるだけシンプルな例を示していきます。

要素の選択とinnerHTMLの代入

innerHTMLを使うためには、まず操作したい要素をJavaScriptで取得します。
例えば、次のようなHTMLがあったとします。

<div id="sample-box">初期のテキスト</div>
<button id="change-button">内容を変更する</button>

ここでは、id="sample-box"が付いた<div>要素の中身を変えたいと考えましょう。
JavaScript側では以下のように書きます。

const sampleBox = document.getElementById("sample-box");
const changeButton = document.getElementById("change-button");

changeButton.addEventListener("click", () => {
  sampleBox.innerHTML = "<p>書き換え後のテキスト</p>";
});

上記の例では、ボタンがクリックされたタイミングでsampleBox要素のinnerHTMLに新しいHTML文字列を代入しています。
これにより、画面上の内容が瞬時に切り替わります。
<p>タグを指定したので、もともとのテキストが消え、新しい段落要素が挿入されるわけです。

基本的なサンプル

もし単純にテキストを置き換えるだけであれば、HTMLタグ無しの文字列を代入しても構いません。
例えば以下のように書けば、文字列だけが表示されます。

sampleBox.innerHTML = "新しいテキストだけ表示します";

この場合は段落などのタグは含まれず、純粋にテキストとして扱われます。
タグでの装飾が不要ならば、こちらのほうがシンプルです。

HTMLタグの書き換え

innerHTMLには、より複雑なHTML構造を入れることもできます。
例えば画像やリストをまとめて書き換えるイメージです。

sampleBox.innerHTML = `
  <ul>
    <li>リスト1</li>
    <li>リスト2</li>
  </ul>
  <img src="some-image.jpg" alt="サンプル画像">
`;

このように、ある程度まとまったHTMLを一度に注入できるのがinnerHTMLの強みといえます。
ただし、整形ミスやタグの閉じ忘れがあると期待通りに表示されないこともあるので注意してください。

複数要素への適用例

innerHTMLは1つの要素だけでなく、複数の要素にも同時に適用できます。
例えば、クラス名が共通の要素をdocument.querySelectorAll()で一括取得し、それぞれにinnerHTMLを代入することが可能です。

const boxes = document.querySelectorAll(".multi-box");

boxes.forEach((box, index) => {
  box.innerHTML = `<p>コンテナ${index + 1}のテキスト</p>`;
});

こうすることで、同じ処理を複数の要素に対してまとめて実行できます。
実務でも、似たような構造をまとめて置き換えるケースは少なくありません。
たとえば複数のカードレイアウトを一斉に生成する場面などで使えます。

innerHTMLと他の方法との比較

innerHTMLと似たような操作をする方法は、JavaScriptにはいくつか存在します。
ここでは代表的なtextContentinnerText、そしてcreateElementなどとの違いを簡単に整理します。

textContentやinnerTextとの違い

textContentinnerTextは、HTMLの要素に含まれるテキスト情報のみを対象にしたプロパティです。
特にinnerTextはCSSのスタイルを考慮して表示されるテキストを取得するといった特徴がありますが、細かい違いはさておき、共通しているのはタグを文字として扱う点です。

もし要素内に<span><strong>といったタグがあっても、textContentで取り出すと、あくまでテキストとして表示されるだけです。
つまり、タグの構造そのものは扱えません。

一方、innerHTMLはタグを含んだ文字列として読み書きできます。
HTMLの構造を直接操作したいのであればinnerHTML、テキスト部分だけを変更したいのであればtextContentやinnerTextを使うとよいでしょう。

createElementとの違い

もう一つ、DOM操作の代表例としてはdocument.createElement()があります。
これは新しいHTML要素をJavaScriptで生成して、DOMツリーに追加・削除する操作を細かく行う方法です。

例えばconst p = document.createElement("p")で段落要素を作り、p.textContent = "内容"としてテキストを設定し、最後にparent.appendChild(p)で親要素に挿入するといった手順になります。
innerHTMLの場合は文字列を代入するだけで複数の要素を一気に生成できるため、短いコードで済む反面、複雑なロジックを組むときはcreateElementのほうが制御しやすい場面もあります。

  • innerHTML: HTMLを文字列としてまとめて書き換えたいときに有利
  • createElement: 要素単位で厳密に操作したい場合に有利

実務では使い分けが大切です。
短いコードで済むinnerHTMLを多用する場合も、読みやすさやセキュリティリスクを考慮しながら導入しましょう。

innerHTMLを使う時の注意点

innerHTMLを使うと、とても手軽にDOMを操作できます。
しかし、実際の開発現場ではいくつか大切な注意点が存在します。

セキュリティ上のリスク

最も気をつけなければならないのが、セキュリティ上のリスクです。
特に、ユーザーが入力した文字列や外部から取得した文字列を直接innerHTMLに注入する場合、予想外のスクリプトが埋め込まれる可能性があります。

たとえば、悪意のあるユーザーが<script>alert("危険");</script>というような文字列を入力したらどうなるでしょうか。
それをinnerHTMLに代入してしまうと、意図せずJavaScriptが実行されてしまうことがあります。

入力内容をそのままinnerHTMLに渡すと、セキュリティリスク(XSS)が発生する可能性が高くなります。
使う際は、不審なタグやスクリプトを除去する仕組みを設けるなどの対策を検討してください。

パフォーマンス面での注意

innerHTMLは、要素内のHTMLをすべて再構築するような仕組みです。
そのため、頻繁に呼び出したり、非常に大きなHTMLブロックを一気に書き換えると、ページの表示が遅くなる場合があります。

小規模なUI変化や、たまに行う更新ならばそこまで問題になりません。
しかし、アニメーション的に何度も書き換えるなど、連続してDOMを更新する場合には注意が必要です。

大規模なプロジェクトでは、パフォーマンス向上のために仮想DOM(バーチャルDOM)を使ったライブラリやフレームワークを導入することが多いです。
innerHTMLだけで複雑なUI更新を管理するのは難易度が上がるため、適度にライブラリの活用を検討するのも一つの手段です。

タグの閉じ忘れや不正なHTML

innerHTMLでHTML文字列を組み立てるとき、うっかりタグを閉じ忘れることがあります。
例えば<div>タグを開いて</div>を書き忘れた場合、ブラウザのレンダリング結果が想定外になるかもしれません。

さらに、重複したIDを含むタグを挿入してしまうと、JavaScriptで要素を取得するときに混乱が生じます。
innerHTMLで構築したHTMLが正しいか、こまめにチェックする癖をつけるとよいでしょう。

innerHTMLの活用例

ここでは、実務でよくある簡単な活用例をいくつか示します。
初心者の方でもイメージしやすいように、UI変更やユーザー入力の表示を取り上げます。

ユーザー入力を動的に表示する

例として、テキストボックスに入力した内容を、リアルタイムで画面に反映させるケースを考えましょう。
以下のHTMLを用意します。

<input type="text" id="user-input" placeholder="何か入力してください">
<div id="output-area"></div>

そしてJavaScriptで次のように記述します。

const userInput = document.getElementById("user-input");
const outputArea = document.getElementById("output-area");

userInput.addEventListener("input", () => {
  const currentValue = userInput.value;
  outputArea.innerHTML = `<p>あなたが入力中の文字列: ${currentValue}</p>`;
});

これにより、テキストボックスに文字を入力するたびに、outputAreaに入力内容が即座に表示されます。
ただし実際には、先ほど解説した通り、ユーザーの入力をそのままHTMLに埋め込むのはXSSリスクがある点に注意してください。

API結果を表示する簡単な例

外部APIを呼び出した結果をHTMLとして整形して表示したいときにもinnerHTMLは便利です。
例えば、仮にfetchなどを使ってサーバーからデータを取得したとしましょう。
取得したデータをテーブルやリスト形式に整形し、まとめてinnerHTMLで挿入するイメージです。

fetch("https://example.com/api/data")
  .then((response) => response.json())
  .then((data) => {
    const resultBox = document.getElementById("result-box");
    let htmlContent = "<ul>";

    data.items.forEach((item) => {
      htmlContent += `<li>${item.name} - ${item.value}</li>`;
    });

    htmlContent += "</ul>";
    resultBox.innerHTML = htmlContent;
  });

こうしてAPIから取得した配列データをループ処理しつつ、文字列として結合して最後に一気に表示します。
これもinnerHTMLなら少ない行数で実装しやすいのがメリットです。
実務では表示部分をテンプレート化したり、エスケープ処理を入れたりしてさらに安全性を高める必要があります。

innerHTMLを使いすぎないための工夫

innerHTMLは便利ですが、使いすぎるとコードが読みにくくなり、セキュリティ面や保守性にも悪影響が出てきます。
ここでは、innerHTMLを乱用せずに開発を進めるための工夫について触れます。

テンプレートを使った開発

HTMLの構造がある程度複雑になる場合、HTML側にあらかじめテンプレート(例えば<template>タグなど)を用意しておき、JavaScriptで複製・挿入する手法があります。
この方法を使えば、いちいちJavaScript側で長いHTML文字列を組み立てる必要がありません。

innerHTMLを使うと、どうしても文字列の中にタグをベタ書きする場面が増えます。
タグの整理が面倒になりやすいので、構造が複雑ならばテンプレート活用を検討するのがよいでしょう。

また、テンプレート以外にもcloneNode()で要素を複製して使う方法などがあります。
コードの可読性とメンテナンス性を保つためにも、プロジェクト規模に合わせて適切な技術選択をすることが重要です。

バーチャルDOMを使ったライブラリの活用

最近では、ReactやVue.jsといったライブラリやフレームワークが一般的になっています。
これらはバーチャルDOMを採用しており、変更が必要な部分だけを効率的に書き換える仕組みです。

innerHTMLを手動で扱うのではなく、コンポーネントや仮想DOMの仕組みに任せることで安全かつ保守しやすくなります。
もちろん、ライブラリを使うにはそれなりの学習が必要ですが、プロジェクトが大きくなるほどinnerHTMLだけでは対応しきれないケースが出てくるでしょう。

ただし、小規模なサイトや単純なサンプルであればinnerHTMLでも十分です。
要件に応じて柔軟に使い分けることが大切です。

innerHTMLのよくあるエラーと対処法

innerHTMLを使い始めたばかりの方は、思わぬところでハマりがちなエラーに遭遇することがあります。
ここでは代表的なものを挙げながら、どう対処すべきかを説明します。

何も表示されないとき

innerHTMLを代入しても画面になにも表示されないケースがあります。
主な原因としては、JavaScriptの実行タイミングがHTML要素の読み込み前になっている、もしくはID指定が間違っている、といったミスが考えられます。

対処法としては、スクリプトを<body>タグの下部で読み込む、あるいはDOMContentLoadedイベントを使ってDOMが構築された後に処理を走らせるようにするといった工夫があります。
また、IDやクラス名が正しいかどうかも確認しましょう。

文字化けが発生するとき

HTMLやJavaScriptファイルの文字コードが一致していないと、innerHTMLで挿入した日本語が文字化けすることがあります。
ファイルのエンコード設定がUTF-8に統一されているかどうかを確認するとよいでしょう。

場合によっては、HTML文書に適切な<meta charset="utf-8">タグが入っていなかったという単純なミスも起こりがちです。
文字化けは原因が多岐にわたるので、環境依存の問題も含めてチェックする必要があります。

コンソールにエラーが出たとき

innerHTML代入時にコンソールエラーが出るケースの一つとして、誤ったHTML構文を入れてしまうことがあげられます。
例えば<div><span>テキスト</div></span>というような入れ子が崩れたタグを挿入すると、ブラウザが強制的に修正したり、エラーを吐いたりすることがあります。

HTML構造の整合性が大きく崩れていると、意図した表示にならないばかりか、スクリプトが途中で止まる可能性もあります。
一度、単独のHTMLファイルでその文字列が正しく描画されるか確認し、問題がないことを確かめてから代入すると安心です。

innerHTMLを活用したUIパターン

innerHTMLはちょっとしたUIパターンをすばやく実装するときにも役立ちます。
以下では、タブ切り替えとモーダルウィンドウに関する簡単な例を示します。

タブ切り替え

複数のコンテンツをタブ状に切り替えるUIを、innerHTMLで実装することも可能です。
それぞれのタブに対応するコンテンツHTMLを切り替えているだけなので、以下のようなイメージで書けます。

const tabButtons = document.querySelectorAll(".tab-button");
const contentBox = document.getElementById("tab-content");

tabButtons.forEach((button) => {
  button.addEventListener("click", () => {
    const content = `<div><h4>${button.dataset.title}</h4><p>ここに詳細を表示</p></div>`;
    contentBox.innerHTML = content;
  });
});

この例では、各ボタンをクリックしたら対応するHTMLブロックをinnerHTMLで切り替えています。
本格的なタブUIを作るには、もっと構造化された仕組みを使うことも多いですが、サンプルレベルならこれでも十分です。

モーダルウィンドウ

モーダルウィンドウも、innerHTMLで大枠を切り替える実装ができます。
例えば、背景のオーバーレイとコンテンツ部分をまとめてinnerHTMLで挿入し、閉じるボタンを押したときにそれらをクリアする、といった要領です。

function openModal() {
  const overlay = document.getElementById("overlay");
  overlay.innerHTML = `
    <div class="modal">
      <button id="close-modal">×</button>
      <div class="modal-content">
        <p>モーダル内部のテキスト</p>
      </div>
    </div>
  `;
  
  const closeModalBtn = document.getElementById("close-modal");
  closeModalBtn.addEventListener("click", () => {
    overlay.innerHTML = ""; // モーダルを消す
  });
}

このように、innerHTMLによって一時的なUIを挿入して、不要になったら空文字列を代入して削除する、というパターンがよく使われます。
もちろん、本格的なモーダルライブラリを使うことも多いですが、単純なニーズならinnerHTMLでも間に合うケースがあります。

innerHTMLとイベントリスナーの組み合わせ

innerHTMLを使って新しく生成した要素にイベントを付与したい場合、いくつかのポイントを押さえておくとスムーズです。
この章では、その基本的な流れや注意点を紹介します。

innerHTMLで生成した要素へのイベント設定

innerHTMLを使ってHTML要素を挿入したあと、対応するJavaScriptイベントを設定する必要があるときがあります。
たとえば先ほどのモーダル例でも、要素を生成した後にイベントリスナーを登録しました。

innerHTMLで要素を生成した瞬間には、まだコード上でその新しい要素を参照していません。
したがって、document.getElementById()document.querySelector()で再度取得し、イベントリスナーを付ける作業が必要です。

もしinnerHTMLの代入前にdocument.getElementById()しようとしても、要素が存在しないため見つかりません。
タイミングに注意し、innerHTMLで要素を用意した後でDOMを取得するようにしましょう。

コールバック関数のポイント

イベントリスナーにはコールバック関数を渡しますが、innerHTMLを利用して要素を更新する中でスコープが混乱してしまうことがあります。
特に、他の変数と名前が衝突したり、閉じるボタンなどの複数の要素に同じIDを与えてしまったりすると、イベントが正しく紐づかない場合があります。

複数の場所でinnerHTMLを使うプロジェクトならば、IDよりもクラスやカスタム属性を使い分ける方法も検討してください。
後述するdata属性などを利用し、要素を一意に特定する方がトラブルを減らせるでしょう。

innerHTMLとカスタム属性の活用

innerHTMLで動的に要素を生成する際、必要な状態やパラメータを埋め込んでおきたい場合があります。
HTMLのカスタム属性を活用すると、後からJavaScriptで読み取れるため便利です。

data属性を使った状態管理

HTMLでは、data-というプレフィックスを付けることで自由にカスタム属性を定義できます。
例えば、data-user-iddata-stateなどがそれに当たります。

<div id="user-list"></div>
function renderUserList(users) {
  const container = document.getElementById("user-list");
  let htmlContent = "<ul>";

  users.forEach((user) => {
    htmlContent += `
      <li data-user-id="${user.id}">
        ${user.name}
      </li>`;
  });

  htmlContent += "</ul>";
  container.innerHTML = htmlContent;
}

このようにしておくと、後からクリックイベントなどを設定する際に、event.target.dataset.userIdのようにしてユーザーIDを取得できます。
innerHTMLでリストをまとめて挿入するときにも、各要素が持つ固有の情報を埋め込みやすくなるわけです。

innerHTMLで生成する要素に属性を設定する

先ほどのように、文字列中にdata-属性を含める形で書いてしまえば、生成後に改めて要素にセットする必要はありません。
ただし、属性値を連結するときに、クォートやエスケープが崩れないよう注意しましょう。

// 変数にバックスラッシュやクォートが含まれていないかチェック
const someValue = "特殊文字を含む値";
const container = document.getElementById("my-container");

container.innerHTML = `<div data-value="${someValue}">表示領域</div>`;

もしsomeValueの内容にダブルクォート"などが含まれていた場合、うまく属性として認識されないかもしれません。
実務ではエスケープ処理を挟んだり、そもそもinnerHTMLではなくsetAttributeを使うほうが安全なケースも多いです。

innerHTMLで意図しない改行・スペースを発生させないコツ

innerHTMLを代入するとき、文字列の書き方によっては余計な空白や改行が入ってしまうことがあります。
ここでは、そういった問題を回避するためのちょっとしたポイントをまとめます。

空白文字の扱い

JavaScriptのテンプレートリテラルで複数行を表記するとき、行末や改行の仕方によってHTMLに不要な空白文字が混入することがあります。
これが原因でレイアウトが崩れる場合もあるため、気になるときは以下のように改行を最小限に留める書き方を工夫するとよいでしょう。

container.innerHTML = `<div><span>テキスト</span></div>`;
// 不要な改行を挟まない

また、CSSでwhite-spaceプロパティがpreになっていると、改行やスペースがそのまま表示されてしまう場合があります。
レイアウトがおかしいと思ったら、このようなCSS設定を疑ってみるのも大切です。

CSSの調整との組み合わせ

innerHTMLで生成される要素が想定よりも広がってしまう、意図しない位置に改行が入る、などの現象は、HTML構造だけでなくCSSの指定も影響します。
inline要素の間にはスペースが入る特性があるので、レイアウトによってはタグ同士を行末で閉じたり、コメントで区切ったりといった工夫が必要になることがあります。

初心者の方はHTMLとCSS、さらにJavaScriptの関係性を整理するのが難しいと感じるかもしれません。
こうした微調整も含め、innerHTMLに埋め込む構造が最終的にどう表示されるか、確認しながら開発を進めるとよいでしょう。

まとめ

innerHTMLを使うと、Webページ上の要素を比較的簡単に書き換えることができます。
要素の中身をまるごと置き換えるため、文字列操作だけでUIを構築できるのが特徴です。

一方で、ユーザー入力をそのまま使用するとセキュリティリスク(XSS)が発生する可能性がありますし、大規模なプロジェクトではパフォーマンスや可読性の問題も出てきます。
innerHTMLはあくまでDOM操作の手段の一つであり、他の方法やフレームワークとの使い分けが大切です。

初心者の皆さんがinnerHTMLに慣れることで、ちょっとしたUI変更やユーザー入力の表示など、多くの場面で手軽に動的処理を実装できるようになるでしょう。
まずは小さなサンプルから試してみて、DOM操作の基礎感覚をつかんでみてください。
そして慣れてきたら、より安全で拡張性の高い方法にも興味を広げていくと、実務に役立つスキルに繋がっていくはずです。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。