innerHTMLとは?JavaScriptでHTML要素の中身を操作する方法

JavaScriptのinnerHTMLプロパティを使ったHTML要素の操作方法を初心者向けに解説。基本的な使い方から実践的な活用例まで詳しく説明します。

Learning Next 運営
40 分で読めます

innerHTMLとは?JavaScriptでHTML要素の中身を操作する方法

みなさん、JavaScriptを使ってWebページの内容を変更したいと思ったことはありませんか?

「ボタンを押したらテキストが変わる機能を作りたい」 「Webページの一部だけを更新したい」

こんな風に思ったことはありませんか?

この記事では、JavaScriptのinnerHTMLプロパティを使ったHTML要素の操作方法を、初心者にも分かりやすく解説します。 基本的な使い方から実用的なテクニックまで、一緒に学んでいきましょう!

innerHTMLって何のこと?

innerHTMLは、HTML要素の内部コンテンツを自由に操作できるプロパティです。

簡単に言うと、「HTML要素の中身を取得したり変更したりする」機能なんです。 例えば、<div>タグの中身を別の内容に変えたり、新しいHTMLを追加したりできます。

イメージとしては、お弁当箱の中身を入れ替えるような感じですね。

基本的な構文

innerHTMLの基本的な使い方は以下の通りです。

// HTML要素を取得
const element = document.getElementById('myElement');
// 内容を取得
const content = element.innerHTML;
// 内容を設定
element.innerHTML = '<p>新しい内容</p>';

この基本構文について詳しく説明しますね。

まず、document.getElementByIdでHTML要素を取得します。

const element = document.getElementById('myElement');

この部分で、id="myElement"という要素をJavaScriptで扱えるようにします。

次に、innerHTMLで内容を取得できます。

const content = element.innerHTML;

element.innerHTMLで、現在の中身を文字列として取得します。

内容を変更したいときは、新しい値を代入します。

element.innerHTML = '<p>新しい内容</p>';

このように、HTMLタグを含む文字列で新しい内容を設定できます。

実際のHTMLとの組み合わせ例

実際のHTMLとJavaScriptの組み合わせ例を見てみましょう。

<!DOCTYPE html>
<html>
<head>
<title>innerHTML サンプル</title>
</head>
<body>
<div id="container">
<p>元の内容</p>
</div>
<button onclick="changeContent()">内容を変更</button>
<script>
function changeContent() {
const container = document.getElementById('container');
container.innerHTML = '<h2>変更された内容</h2><p>新しいパラグラフです</p>';
}
</script>
</body>
</html>

この例の動作を詳しく説明します。

HTMLで基本的な構造を作ります。

<div id="container">
<p>元の内容</p>
</div>

id="container"で要素に名前をつけて、初期内容を設定します。

ボタンをクリックしたときの処理を定義します。

function changeContent() {
const container = document.getElementById('container');
container.innerHTML = '<h2>変更された内容</h2><p>新しいパラグラフです</p>';
}

ボタンがクリックされると、<div>の中身が完全に新しい内容に置き換わります。

innerHTMLの基本的な使い方

内容の取得

HTML要素の現在の内容を取得する方法です。

<div id="sample">
<h3>タイトル</h3>
<p>説明文</p>
</div>
<script>
// 要素の内容を取得
const sampleDiv = document.getElementById('sample');
const currentContent = sampleDiv.innerHTML;
console.log(currentContent);
// 出力: '<h3>タイトル</h3><p>説明文</p>'
</script>

この例について詳しく説明しますね。

getElementByIdで対象の要素を取得します。

const sampleDiv = document.getElementById('sample');

要素が取得できたら、innerHTMLで中身を取得します。

const currentContent = sampleDiv.innerHTML;

currentContentには、HTMLタグも含めた中身が文字列として格納されます。

console.logで確認すると、<h3>タイトル</h3><p>説明文</p>という文字列が表示されます。

内容の設定

HTML要素に新しい内容を設定する方法です。

// 基本的な設定
const element = document.getElementById('target');
element.innerHTML = '<strong>太字のテキスト</strong>';
// 複数行のHTML
element.innerHTML = `
<h2>見出し</h2>
<p>段落1</p>
<p>段落2</p>
<ul>
<li>項目1</li>
<li>項目2</li>
</ul>
`;

設定方法のポイントを説明します。

シンプルなHTMLの場合は、直接文字列を代入します。

element.innerHTML = '<strong>太字のテキスト</strong>';

複数行のHTMLを設定したい場合は、テンプレートリテラル(バッククォート)を使います。

element.innerHTML = `
<h2>見出し</h2>
<p>段落1</p>
`;

バッククォート(`)を使うことで、改行を含む複数行の文字列を書けます。

内容の追加

既存の内容に新しい内容を追加する方法です。

const container = document.getElementById('container');
// 既存内容に追加
container.innerHTML += '<p>追加された段落</p>';
// より安全な追加方法
const newContent = '<div>新しいコンテンツ</div>';
container.innerHTML = container.innerHTML + newContent;

追加方法について詳しく説明します。

+=演算子を使うと、既存の内容に新しい内容を追加できます。

container.innerHTML += '<p>追加された段落</p>';

これは以下と同じ意味です。

container.innerHTML = container.innerHTML + '<p>追加された段落</p>';

既存の内容を保持したまま、新しい内容を末尾に追加できます。

実践的な使用例

動的なリスト作成

配列のデータからHTMLリストを動的に生成する例です。

<div id="fruit-list"></div>
<button onclick="createFruitList()">フルーツリストを作成</button>
<script>
function createFruitList() {
const fruits = ['りんご', 'バナナ', 'オレンジ', 'ぶどう', 'いちご'];
const listContainer = document.getElementById('fruit-list');
let htmlContent = '<h3>フルーツリスト</h3><ul>';
fruits.forEach((fruit, index) => {
htmlContent += `<li>${index + 1}. ${fruit}</li>`;
});
htmlContent += '</ul>';
listContainer.innerHTML = htmlContent;
}
</script>

この動的リスト作成の流れを詳しく説明します。

まず、フルーツの配列を用意します。

const fruits = ['りんご', 'バナナ', 'オレンジ', 'ぶどう', 'いちご'];

空の文字列から始めて、HTMLを組み立てていきます。

let htmlContent = '<h3>フルーツリスト</h3><ul>';

<ul>タグでリストの開始を作ります。

forEachで配列の各要素をリストアイテムに変換します。

fruits.forEach((fruit, index) => {
htmlContent += `<li>${index + 1}. ${fruit}</li>`;
});

index + 1で番号を振って、各フルーツを<li>タグで囲みます。

最後にリストを閉じて、要素に設定します。

htmlContent += '</ul>';
listContainer.innerHTML = htmlContent;

完成したHTMLをinnerHTMLで要素に設定します。

ユーザー情報の表示

オブジェクトのデータからユーザー情報を表示する例です。

function displayUserInfo(user) {
const userContainer = document.getElementById('user-info');
userContainer.innerHTML = `
<div class="user-card">
<h2>${user.name}</h2>
<p><strong>年齢:</strong> ${user.age}</p>
<p><strong>職業:</strong> ${user.job}</p>
<p><strong>趣味:</strong> ${user.hobbies.join(', ')}</p>
<p><strong>登録日:</strong> ${user.registeredAt}</p>
</div>
`;
}
// 使用例
const userData = {
name: '田中太郎',
age: 28,
job: 'エンジニア',
hobbies: ['読書', '映画鑑賞', 'プログラミング'],
registeredAt: '2024-01-15'
};
// ボタンクリックで表示
document.getElementById('show-user').addEventListener('click', function() {
displayUserInfo(userData);
});

ユーザー情報表示の仕組みを詳しく説明します。

ユーザーデータをオブジェクトで定義します。

const userData = {
name: '田中太郎',
age: 28,
job: 'エンジニア',
hobbies: ['読書', '映画鑑賞', 'プログラミング'],
registeredAt: '2024-01-15'
};

各プロパティにユーザーの情報を格納します。

テンプレートリテラルでHTMLを組み立てます。

userContainer.innerHTML = `
<div class="user-card">
<h2>${user.name}</h2>
<p><strong>年齢:</strong> ${user.age}</p>
</div>
`;

${user.name}のように、オブジェクトのプロパティを埋め込みます。

user.hobbies.join(', ')で配列を文字列に変換します。

<p><strong>趣味:</strong> ${user.hobbies.join(', ')}</p>

配列の要素をカンマ区切りの文字列にして表示します。

テーブルの動的生成

配列データからHTMLテーブルを生成する例です。

function createProductTable(products) {
const tableContainer = document.getElementById('product-table');
let tableHTML = `
<table border="1" style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th>商品名</th>
<th>価格</th>
<th>カテゴリー</th>
<th>在庫</th>
</tr>
</thead>
<tbody>
`;
products.forEach(product => {
tableHTML += `
<tr>
<td>${product.name}</td>
<td>¥${product.price.toLocaleString()}</td>
<td>${product.category}</td>
<td>${product.stock > 0 ? product.stock + '個' : '在庫なし'}</td>
</tr>
`;
});
tableHTML += '</tbody></table>';
tableContainer.innerHTML = tableHTML;
}
// サンプルデータ
const products = [
{ name: 'ノートPC', price: 120000, category: '電子機器', stock: 5 },
{ name: 'マウス', price: 2500, category: '電子機器', stock: 15 },
{ name: '本', price: 1200, category: '書籍', stock: 0 },
{ name: 'ペン', price: 300, category: '文具', stock: 30 }
];
createProductTable(products);

テーブル生成の流れを詳しく説明します。

まず、テーブルのヘッダー部分を作ります。

let tableHTML = `
<table border="1" style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th>商品名</th>
<th>価格</th>
<th>カテゴリー</th>
<th>在庫</th>
</tr>
</thead>
<tbody>
`;

<thead>でヘッダー、<tbody>でデータ部分を分けます。

商品データを1つずつ行に変換します。

products.forEach(product => {
tableHTML += `
<tr>
<td>${product.name}</td>
<td>¥${product.price.toLocaleString()}</td>
<td>${product.category}</td>
<td>${product.stock > 0 ? product.stock + '個' : '在庫なし'}</td>
</tr>
`;
});

product.price.toLocaleString()で価格を3桁区切りで表示します。

在庫の表示では条件分岐を使います。

${product.stock > 0 ? product.stock + '個' : '在庫なし'}

在庫が0より大きければ個数を、そうでなければ「在庫なし」を表示します。

カードコンポーネントの作成

再利用可能なカードコンポーネントを作成する例です。

<div id="card-container"></div>
<button onclick="addCard()">カードを追加</button>
<style>
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
max-width: 300px;
}
.card-title {
font-size: 1.2em;
font-weight: bold;
margin-bottom: 8px;
}
.card-content {
color: #666;
line-height: 1.4;
}
.card-footer {
margin-top: 12px;
padding-top: 8px;
border-top: 1px solid #eee;
font-size: 0.9em;
color: #888;
}
</style>
<script>
function createCard(title, content, footer) {
return `
<div class="card">
<div class="card-title">${title}</div>
<div class="card-content">${content}</div>
<div class="card-footer">${footer}</div>
</div>
`;
}
function addCard() {
const container = document.getElementById('card-container');
const cardCount = container.children.length + 1;
const newCard = createCard(
`カード ${cardCount}`,
`これは${cardCount}番目のカードです。innerHTMLを使って動的に生成されました。`,
`作成日: ${new Date().toLocaleString()}`
);
container.innerHTML += newCard;
}
// 初期カードを追加
addCard();
</script>

カードコンポーネントの仕組みを詳しく説明します。

まず、カード作成用の関数を用意します。

function createCard(title, content, footer) {
return `
<div class="card">
<div class="card-title">${title}</div>
<div class="card-content">${content}</div>
<div class="card-footer">${footer}</div>
</div>
`;
}

この関数は、タイトル、内容、フッターを受け取ってHTMLを返します。

カード追加の処理では、現在のカード数を数えます。

const cardCount = container.children.length + 1;

container.children.lengthで現在の子要素数を取得し、1を足して次の番号にします。

新しいカードを作成して追加します。

const newCard = createCard(
`カード ${cardCount}`,
`これは${cardCount}番目のカードです。innerHTMLを使って動的に生成されました。`,
`作成日: ${new Date().toLocaleString()}`
);
container.innerHTML += newCard;

作成したHTMLを既存のコンテナに追加します。

セキュリティとベストプラクティス

XSS攻撃の防止

innerHTMLを使用する際のセキュリティ対策です。

// 危険な例:ユーザー入力をそのまま使用
function unsafeDisplay(userInput) {
const container = document.getElementById('container');
container.innerHTML = userInput; // XSS攻撃の可能性
}
// 安全な例:HTMLエスケープを行う
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function safeDisplay(userInput) {
const container = document.getElementById('container');
const escapedInput = escapeHtml(userInput);
container.innerHTML = `<p>${escapedInput}</p>`;
}
// より安全な代替方法:textContentを使用
function safestDisplay(userInput) {
const container = document.getElementById('container');
const paragraph = document.createElement('p');
paragraph.textContent = userInput; // 自動的にエスケープされる
container.innerHTML = ''; // 既存内容をクリア
container.appendChild(paragraph);
}

セキュリティ対策について詳しく説明します。

ユーザーからの入力をそのまま使うのは危険です。

container.innerHTML = userInput; // XSS攻撃の可能性

悪意のあるスクリプトが実行される可能性があります。

HTMLエスケープ関数で安全にします。

function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}

この関数で、HTMLタグを文字列として扱えます。

最も安全な方法はtextContentを使うことです。

paragraph.textContent = userInput; // 自動的にエスケープされる

textContentは自動的にHTMLタグを無効化してくれます。

パフォーマンスの考慮

大量のDOM操作を効率的に行う方法です。

// 非効率な例:要素ごとに更新
function inefficientUpdate(items) {
const container = document.getElementById('container');
container.innerHTML = ''; // 初期化
items.forEach(item => {
container.innerHTML += `<div>${item}</div>`; // 毎回再描画
});
}
// 効率的な例:一度にまとめて更新
function efficientUpdate(items) {
const container = document.getElementById('container');
let htmlContent = '';
items.forEach(item => {
htmlContent += `<div>${item}</div>`;
});
container.innerHTML = htmlContent; // 一度だけ更新
}
// DocumentFragmentを使った最適化
function optimizedUpdate(items) {
const container = document.getElementById('container');
const fragment = document.createDocumentFragment();
items.forEach(item => {
const div = document.createElement('div');
div.textContent = item;
fragment.appendChild(div);
});
container.innerHTML = ''; // 既存内容をクリア
container.appendChild(fragment); // 一度にDOM追加
}

パフォーマンス向上のポイントを説明します。

毎回innerHTMLを更新するのは非効率です。

container.innerHTML += `<div>${item}</div>`; // 毎回再描画

この方法だと、毎回ページ全体が再描画されてしまいます。

文字列をまとめてから一度に更新する方が効率的です。

let htmlContent = '';
items.forEach(item => {
htmlContent += `<div>${item}</div>`;
});
container.innerHTML = htmlContent; // 一度だけ更新

最も効率的なのはDocumentFragmentを使う方法です。

const fragment = document.createDocumentFragment();

DocumentFragmentを使うと、メモリ上で要素を組み立てて一度にDOMに追加できます。

innerHTMLの代替手法

textContentとの使い分け

innerHTMLとtextContentの適切な使い分けです。

const element = document.getElementById('sample');
// HTMLタグを含むコンテンツを設定したい場合
element.innerHTML = '<strong>太字</strong>のテキスト';
// プレーンテキストのみを設定したい場合(安全)
element.textContent = 'プレーンテキスト';
// 既存内容の取得比較
console.log('innerHTML:', element.innerHTML); // '<strong>太字</strong>のテキスト'
console.log('textContent:', element.textContent); // 'プレーンテキスト'

使い分けのポイントを説明します。

HTMLタグを含む内容を表示したい場合はinnerHTMLを使います。

element.innerHTML = '<strong>太字</strong>のテキスト';

この場合、「太字」の部分が実際に太字で表示されます。

安全にテキストのみを表示したい場合はtextContentを使います。

element.textContent = 'プレーンテキスト';

textContentはHTMLタグを自動的にエスケープしてくれます。

insertAdjacentHTMLの活用

より柔軟なHTML挿入が可能なinsertAdjacentHTMLです。

const targetElement = document.getElementById('target');
// 要素の前に挿入
targetElement.insertAdjacentHTML('beforebegin', '<p>要素の前</p>');
// 要素内の最初に挿入
targetElement.insertAdjacentHTML('afterbegin', '<p>要素内の最初</p>');
// 要素内の最後に挿入
targetElement.insertAdjacentHTML('beforeend', '<p>要素内の最後</p>');
// 要素の後に挿入
targetElement.insertAdjacentHTML('afterend', '<p>要素の後</p>');

insertAdjacentHTMLの便利な点を説明します。

innerHTMLだと既存の内容を全て置き換えてしまいます。

element.innerHTML = '<p>新しい内容</p>'; // 既存内容は消える

insertAdjacentHTMLなら、好きな位置に挿入できます。

targetElement.insertAdjacentHTML('beforeend', '<p>要素内の最後</p>');

既存の内容を保持したまま、新しい内容を追加できます。

実践的なWebアプリケーション例

ToDoリストアプリケーション

innerHTMLを使った簡単なToDoリストの実装例です。

<!DOCTYPE html>
<html>
<head>
<title>ToDoリスト</title>
<style>
.todo-container {
max-width: 400px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
.todo-input {
width: 70%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
.add-button {
width: 25%;
padding: 8px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px;
margin: 5px 0;
background-color: #f8f9fa;
border-radius: 4px;
}
.todo-item.completed {
text-decoration: line-through;
opacity: 0.6;
}
.delete-button {
background-color: #dc3545;
color: white;
border: none;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="todo-container">
<h2>ToDoリスト</h2>
<div>
<input type="text" id="todo-input" class="todo-input" placeholder="新しいタスクを入力">
<button onclick="addTodo()" class="add-button">追加</button>
</div>
<div id="todo-list"></div>
</div>
<script>
let todos = [];
let nextId = 1;
function addTodo() {
const input = document.getElementById('todo-input');
const text = input.value.trim();
if (text === '') {
alert('タスクを入力してください');
return;
}
todos.push({
id: nextId++,
text: text,
completed: false
});
input.value = '';
renderTodos();
}
function toggleTodo(id) {
const todo = todos.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
renderTodos();
}
}
function deleteTodo(id) {
todos = todos.filter(t => t.id !== id);
renderTodos();
}
function renderTodos() {
const todoList = document.getElementById('todo-list');
if (todos.length === 0) {
todoList.innerHTML = '<p style="text-align: center; color: #666;">タスクがありません</p>';
return;
}
let html = '';
todos.forEach(todo => {
html += `
<div class="todo-item ${todo.completed ? 'completed' : ''}">
<span onclick="toggleTodo(${todo.id})" style="cursor: pointer;">
${todo.text}
</span>
<button onclick="deleteTodo(${todo.id})" class="delete-button">
削除
</button>
</div>
`;
});
todoList.innerHTML = html;
}
// Enterキーでタスク追加
document.getElementById('todo-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
addTodo();
}
});
// 初期表示
renderTodos();
</script>
</body>
</html>

ToDoリストの仕組みを詳しく説明します。

まず、タスクを管理する配列を用意します。

let todos = [];
let nextId = 1;

todos配列でタスクを管理し、nextIdで一意のIDを生成します。

新しいタスクを追加する処理です。

function addTodo() {
const input = document.getElementById('todo-input');
const text = input.value.trim();
if (text === '') {
alert('タスクを入力してください');
return;
}
todos.push({
id: nextId++,
text: text,
completed: false
});
input.value = '';
renderTodos();
}

入力値を取得して、空でなければ配列に追加します。

タスクの完了状態を切り替える処理です。

function toggleTodo(id) {
const todo = todos.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
renderTodos();
}
}

findメソッドで対象のタスクを見つけて、完了状態を反転させます。

画面表示を更新する処理です。

function renderTodos() {
const todoList = document.getElementById('todo-list');
if (todos.length === 0) {
todoList.innerHTML = '<p style="text-align: center; color: #666;">タスクがありません</p>';
return;
}
let html = '';
todos.forEach(todo => {
html += `
<div class="todo-item ${todo.completed ? 'completed' : ''}">
<span onclick="toggleTodo(${todo.id})" style="cursor: pointer;">
${todo.text}
</span>
<button onclick="deleteTodo(${todo.id})" class="delete-button">
削除
</button>
</div>
`;
});
todoList.innerHTML = html;
}

タスクが空の場合は、メッセージを表示します。 タスクがある場合は、全てのタスクをHTMLに変換して一度に表示します。

まとめ

JavaScriptのinnerHTMLプロパティは、動的なWebページ作成において非常に重要で実用的な機能です。

重要なポイント

  • innerHTMLはHTML要素の内部コンテンツを自由に操作できる
  • 取得と設定の両方が可能で、複雑なHTMLも扱える
  • 動的なリスト、テーブル、フォーム生成など幅広い用途で活用可能
  • セキュリティ対策(XSSの防止)が重要
  • パフォーマンスを考慮した実装が必要

実践のコツ

  • ユーザー入力を扱う際は必ずエスケープ処理を行う
  • 大量のDOM操作は一度にまとめて実行する
  • 適切な場面でtextContentやinsertAdjacentHTMLも活用する
  • セキュリティとパフォーマンスを常に意識する

innerHTMLを適切に活用することで、ユーザーの操作に応じて柔軟に変化するインタラクティブなWebページを作成できます!

今回学んだテクニックを使って、ぜひ自分だけの動的なWebアプリケーションを作ってみてください。 きっと、もっとJavaScriptが楽しくなりますよ!

関連記事