document.createElementでHTMLを生成する8つの方法

JavaScriptのdocument.createElementメソッドを使ってHTMLを動的に生成するJS
この記事は約25分で読めます。

※本記事のコンテンツは、利用目的を問わずご活用いただけます。実務経験10000時間以上のエンジニアが監修しており、常に解説内容のわかりやすさや記事の品質に注力しておりますので、不具合・分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。(理解できない部分などの個別相談も無償で承っております)
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●document.createElementとは?

JavaScriptを使ってWebページを動的に操作する際、document.createElementは非常に重要な役割を果たします。

このメソッドを使えば、新しいHTML要素をプログラム的に生成し、ページに追加することができるのです。

document.createElementは、DOM(Document Object Model)操作の一環として使用されます。

DOMとは、WebページをJavaScriptから操作するためのインターフェースで、ページ上の要素を取得したり、新しい要素を追加したり、既存の要素を変更したりできます。

○document.createElementの基本的な使い方

では、document.createElementの基本的な使い方を見ていきましょう。

このメソッドは、指定したタグ名の新しい要素を生成します。

生成された要素は、ページには追加されていない状態なので、別途appendChild()などのメソッドを使って、ページ上の適切な位置に挿入する必要があります。

// 新しいdiv要素を生成
const newDiv = document.createElement('div');

// 生成した要素をページに追加
document.body.appendChild(newDiv);

この例では、まずcreateElement()を使って新しいdiv要素を生成しています。

生成された要素は、newDiv変数に格納されます。

次に、appendChild()メソッドを使って、そのdiv要素をページのbody要素の子要素として追加しています。

○サンプルコード1:新しい要素を作成して追加する

実際に、document.createElementを使ってページに新しい要素を追加するサンプルコードを見てみましょう。

// 新しいp要素を生成
const newParagraph = document.createElement('p');

// テキストノードを作成
const text = document.createTextNode('これは新しく追加されたパラグラフです。');

// テキストノードをp要素に追加
newParagraph.appendChild(text);

// p要素をページのbody要素に追加
document.body.appendChild(newParagraph);

このコードでは、次のような手順で新しいp要素をページに追加しています。

  1. createElement()を使って新しいp要素を生成し、newParagraph変数に格納
  2. createTextNode()を使ってテキストノードを作成し、text変数に格納
  3. appendChild()を使ってテキストノードをp要素の子要素として追加
  4. 最後に、p要素をページのbody要素の子要素として追加

実行すると、ページの最後に「これは新しく追加されたパラグラフです。」というテキストを持つp要素が追加されます。

○サンプルコード2:属性を設定する

createElement()で生成した要素に属性を設定するには、setAttribute()メソッドを使用します。

// 新しいimg要素を生成
const newImage = document.createElement('img');

// src属性を設定
newImage.setAttribute('src', 'path/to/image.jpg');

// alt属性を設定
newImage.setAttribute('alt', '代替テキスト');

// img要素をページに追加
document.body.appendChild(newImage);

ここでは、img要素を生成し、src属性とalt属性を設定しています。

setAttribute()の第一引数に属性名、第二引数に属性値を指定します。最後に、生成したimg要素をページに追加しています。

実行すると、指定したパスの画像を表示するimg要素が、ページの最後に追加されます。

alt属性には「代替テキスト」が設定されます。

●テキストノードの作成と追加

さて、document.createElementを使って新しい要素を生成できるようになりましたが、肝心の要素の中身はまだ空っぽのままです。

せっかく要素を作っても、テキストがなければ意味がありませんよね。そこで登場するのが、テキストノードです。

テキストノードとは、HTML要素の中に実際のテキストを持つためのノードで、createTextNode()メソッドを使って生成します。

生成したテキストノードを要素に追加することで、要素にテキストを設定できるのです。

○サンプルコード3:テキストノードを作成して追加する

それでは、先ほど作成したp要素に、テキストノードを追加してみましょう。

// 新しいp要素を生成
const newParagraph = document.createElement('p');

// テキストノードを作成
const text = document.createTextNode('これは動的に生成されたテキストです。');

// テキストノードをp要素に追加
newParagraph.appendChild(text);

// p要素をページに追加
document.body.appendChild(newParagraph);

createTextNode()メソッドに、設定したいテキストを引数として渡すことで、テキストノードを生成します。

生成されたテキストノードは、appendChild()メソッドを使って、p要素の子ノードとして追加されています。

実行すると、ページ上に「これは動的に生成されたテキストです。」という内容のp要素が追加されます。

○サンプルコード4:複数の要素とテキストノードを組み合わせる

もちろん、複数の要素とテキストノードを組み合わせて、より複雑な構造を作ることもできます。

次の例では、ul要素の中に複数のli要素を動的に生成し、それぞれにテキストを設定しています。

// ul要素を生成
const list = document.createElement('ul');

// 3つのli要素を生成し、ul要素に追加
for (let i = 0; i < 3; i++) {
  const listItem = document.createElement('li');
  const text = document.createTextNode(`アイテム ${i + 1}`);
  listItem.appendChild(text);
  list.appendChild(listItem);
}

// ul要素をページに追加
document.body.appendChild(list);

for文を使って3回繰り返し処理を行い、cada vezにli要素を生成しています。

テキストノードには、 アイテム ${i + 1} という形式で番号を設定しています。

生成されたli要素は、ul要素の子要素として追加されます。

実行すると、ページ上に、次のようなリストが表示されます。

  • アイテム 1
  • アイテム 2
  • アイテム 3

このように、document.createElementとcreateTextNodeを組み合わせることで、動的に生成した要素に好きなテキストを設定できます。

このメソッドを駆使すれば、プログラムで柔軟にページ構造を操作できるようになるのです。

●要素の複製とクローン

ここまでで、document.createElementを使って新しい要素を生成し、ページに追加する方法を学びました。

でも、考えてみると、似たような要素を何度も生成するのって、ちょっと面倒ですよね。

もし、すでにあるHTML要素と同じものをコピーできたら、もっと効率的なコーディングができそうです。

実は、JavaScriptにはそんな要望に応えてくれるメソッドがあるんです。

cloneNode()というメソッドを使えば、既存の要素を複製することができます。

これを使えば、同じ構造の要素を何度も作る手間が省けそうですね。

○サンプルコード5:既存の要素を複製する

それでは、実際にcloneNode()を使って、要素を複製してみましょう。

// 複製元の要素を取得
const originalElement = document.getElementById('original');

// 要素を複製
const clonedElement = originalElement.cloneNode(true);

// 複製した要素のIDを変更
clonedElement.id = 'cloned';

// 複製した要素をページに追加
document.body.appendChild(clonedElement);

このコードでは、まず、ID属性が’original’の要素を取得しています。

次に、cloneNode()メソッドを使って、その要素の複製を作成しています。

cloneNode()メソッドに引数trueを渡すことで、子要素も含めて要素全体を複製するよう指定しています。

複製された要素は、元の要素とまったく同じ構造とコンテンツを持ちますが、IDなどの一部の属性は複製されません。

そこで、複製後の要素のIDを’cloned’に変更し、ページに追加しています。

実行すると、ページ上に、元の要素と同じ構造とコンテンツを持つ新しい要素が追加されます。

ただし、IDは’cloned’に変更されています。

○サンプルコード6:要素の深いクローンを作成する

cloneNode()メソッドには、引数にtrueを渡すかfalseを渡すかで、子要素も含めて複製するかどうかを指定できます。

これを使い分けることで、要素の浅いクローンと深いクローンを使い分けられます。

// 複製元の要素を取得
const originalElement = document.getElementById('original');

// 要素の浅いクローンを作成
const shallowClone = originalElement.cloneNode(false);

// 要素の深いクローンを作成
const deepClone = originalElement.cloneNode(true);

// 浅いクローンと深いクローンをページに追加
document.body.appendChild(shallowClone);
document.body.appendChild(deepClone);

cloneNode(false)とすることで、要素自体は複製されますが、子要素は複製されない浅いクローンが作成されます。

一方、cloneNode(true)とすることで、子要素も含めて複製される深いクローンが作成されます。

実行すると、ページ上に、元の要素の浅いクローンと深いクローンが追加されます。

浅いクローンは子要素を持たず、深いクローンは子要素も含めて複製されています。

●フラグメントの活用

さて、ここまでで、document.createElementを使ってHTMLを動的に生成する方法を学んできました。

新しい要素を作成したり、テキストノードを追加したり、要素を複製したりと、様々な操作ができるようになりましたね。

でも、ちょっと考えてみてください。

もし、たくさんの要素を一度に追加しようとしたら、どうなるでしょうか。

実は、要素を1つ1つページに追加していくと、追加するたびにページのレンダリングが発生し、パフォーマンスに影響を与えてしまうんです。

特に、大量の要素を追加する場合は、ページの表示が遅くなったり、ブラウザが一時的にフリーズしたりする可能性もあります。

そんな時に役立つのが、ドキュメントフラグメントです。

ドキュメントフラグメントとは、ページとは別の仮想的なツリー構造で、要素を一時的に保持しておくことができます。

フラグメントに要素を追加しても、ページのレンダリングは発生しません。

そして、フラグメントごとページに追加することで、一度のレンダリングですべての要素を反映できるんです。

○サンプルコード7:ドキュメントフラグメントを使用する

それでは、ドキュメントフラグメントを使って、複数の要素をページに追加するサンプルコードを見てみましょう。

// ドキュメントフラグメントを作成
const fragment = document.createDocumentFragment();

// フラグメントに複数の要素を追加
for (let i = 0; i < 5; i++) {
  const p = document.createElement('p');
  p.textContent = `パラグラフ ${i + 1}`;
  fragment.appendChild(p);
}

// フラグメントごとページに追加
document.body.appendChild(fragment);

まず、createDocumentFragment()メソッドを使って、新しいドキュメントフラグメントを作成しています。

次に、for文を使って5回繰り返し処理を行い、cada vezに新しいp要素を生成し、フラグメントに追加しています。

ここで重要なのは、p要素をページではなくフラグメントに追加している点です。

これにより、ページのレンダリングは発生せず、パフォーマンスへの影響を最小限に抑えられます。

最後に、appendChild()メソッドを使って、フラグメント全体をページのbody要素に追加しています。

これにより、フラグメントに追加されたすべての要素が一度にページに反映されます。

実行すると、ページ上に、「パラグラフ 1」から「パラグラフ 5」までのテキストを持つp要素が5つ追加されます。

○サンプルコード8:複雑なHTML構造をフラグメントで構築する

ドキュメントフラグメントは、より複雑なHTML構造を効率的に構築する際にも威力を発揮します。

次の例では、テーブル要素を動的に生成し、フラグメントを使って一度に追加しています。

// ドキュメントフラグメントを作成
const fragment = document.createDocumentFragment();

// テーブル要素を生成
const table = document.createElement('table');

// テーブルヘッダーを生成
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const headers = ['ヘッダー1', 'ヘッダー2', 'ヘッダー3'];

headers.forEach(headerText => {
  const th = document.createElement('th');
  th.textContent = headerText;
  headerRow.appendChild(th);
});

thead.appendChild(headerRow);
table.appendChild(thead);

// テーブルボディを生成
const tbody = document.createElement('tbody');

for (let i = 0; i < 3; i++) {
  const row = document.createElement('tr');
  for (let j = 0; j < 3; j++) {
    const cell = document.createElement('td');
    cell.textContent = `セル (${i + 1}, ${j + 1})`;
    row.appendChild(cell);
  }
  tbody.appendChild(row);
}

table.appendChild(tbody);

// テーブルをフラグメントに追加
fragment.appendChild(table);

// フラグメントごとページに追加
document.body.appendChild(fragment);

このコードでは、まずテーブル要素(table)を生成し、ヘッダー行(thead)とボディ部分(tbody)を別々に構築しています。

ヘッダー行には3つのヘッダーセル(th)を、ボディ部分には3行3列のデータセル(td)を動的に生成して追加しています。

ポイントは、すべての要素をいきなりページに追加するのではなく、一旦フラグメントに追加している点です。

テーブル要素をフラグメントに追加し、最後にフラグメントごとページに追加することで、複雑な構造でも効率的に生成できます。

実行すると、ページ上に、3行3列のテーブルが追加されます。

各セルには「セル (1, 1)」から「セル (3, 3)」までのテキストが表示されます。

●よくあるエラーと対処法

document.createElementを使ってHTML要素を動的に生成していると、時々思わぬエラーに遭遇することがあります。

特に、初めてDOM操作に挑戦する人にとっては、エラーメッセージを見ても何が原因なのかわからず、頭を抱えてしまうこともあるでしょう。

でも、大丈夫です。

エラーは誰にでも起こりうるものですし、むしろエラーと向き合うことで、よりJavaScriptへの理解が深まるはずです。

ここでは、document.createElementを使う際によく遭遇するエラーとその対処法を見ていきましょう。

○要素の追加位置を間違える

JavaScript初心者が陥りがちなエラーの1つが、生成した要素の追加位置を間違えてしまうことです。

例えば。次のようなコードを見てみましょう。

// p要素を生成
const p = document.createElement('p');
p.textContent = '新しい段落';

// body要素を取得
const body = document.getElementsByTagName('body');

// p要素をbody要素に追加
body.appendChild(p);

このコードの目的は、新しいp要素を生成し、それをbody要素の子要素として追加することです。

しかし、実際にこのコードを実行すると、エラーが発生してしまいます。

エラーメッセージ

Uncaught TypeError: body.appendChild is not a function

原因は、getElementsByTagName()メソッドが返すのは要素の配列(正確にはNodeList)だということです。body要素は1つしかありませんが、それでも配列として返されます。

そのため、body[0]のようにインデックスを指定して要素を取得する必要があります。

修正後のコード

// p要素を生成
const p = document.createElement('p');
p.textContent = '新しい段落';

// body要素を取得
const body = document.getElementsByTagName('body')[0];

// p要素をbody要素に追加
body.appendChild(p);

body[0]とすることで、body要素を正しく取得できます。

これでエラーが解消され、p要素がページに追加されるはずです。

○属性名や値の指定ミス

createElement()で要素を生成した後、setAttribute()メソッドを使って属性を設定することがよくあります。

しかし、属性名や値を間違えて指定してしまうと、エラーが発生したり、意図しない動作になったりします。

例えば、次のようなコードを見てみましょう。

// img要素を生成
const img = document.createElement('img');

// srcとaltを設定
img.setAttribute('src', 'path/to/image.jpg');
img.setAttribute('alt', '代替テキスト');
img.setAttribute('width', 200);

このコードでは、img要素を生成し、src属性、alt属性、width属性を設定しています。

しかし、width属性の値を数値で指定しているため、実際にはwidth属性が正しく設定されません。

width属性のような数値を受け取る属性は、数値を文字列として指定する必要があります。

そのため、次のように修正します。

修正後のコード

// img要素を生成
const img = document.createElement('img');

// srcとaltを設定
img.setAttribute('src', 'path/to/image.jpg');
img.setAttribute('alt', '代替テキスト');
img.setAttribute('width', '200');

こうすることで、width属性が正しく設定され、意図したサイズの画像が表示されるようになります。

属性の指定には細心の注意を払い、属性名のスペルミスや値の型の間違いに気をつけましょう。

○メモリリークに注意

document.createElementを使って大量の要素を生成する場合、メモリリークに注意が必要です。

メモリリークとは、使われなくなったメモリが解放されずに蓄積していく現象のことです。

例えば、次のようなコードは、メモリリークを引き起こす可能性があります。

function createElements() {
  for (let i = 0; i < 1000; i++) {
    const div = document.createElement('div');
    div.textContent = `要素 ${i}`;
    document.body.appendChild(div);
  }
}

// 1秒ごとにcreateElements()を呼び出す
setInterval(createElements, 1000);

このコードでは、createElements()関数が1秒ごとに呼び出され、cada vez1000個のdiv要素が生成されてページに追加されます。

しかし、古い要素は削除されないため、どんどんメモリが消費されていきます。

このようなメモリリークを防ぐには、不要になった要素を適切にページから削除する必要があります。例えば、次のように修正できます。

修正後のコード

function createElements() {
  // 既存の要素を削除
  const elements = document.querySelectorAll('div');
  elements.forEach(element => element.remove());

  // 新しい要素を生成
  for (let i = 0; i < 1000; i++) {
    const div = document.createElement('div');
    div.textContent = `要素 ${i}`;
    document.body.appendChild(div);
  }
}

// 1秒ごとにcreateElements()を呼び出す
setInterval(createElements, 1000);

このように、createElements()関数の中で、まず既存のdiv要素をすべて削除してから、新しい要素を生成するようにしています。

これにより、不要になった要素がメモリから解放され、メモリリークを防ぐことができます。

document.createElementを使う際は、生成した要素の適切な管理を心がけ、メモリリークに注意しましょう。

特に、大量の要素を動的に生成する場合は、不要になった要素をこまめに削除するようにしてください。

●document.createElementの応用例

ここまでdocument.createElementの基本的な使い方から、よくあるエラーと対処法まで学んできました。

もうこれで、動的にHTMLを生成するスキルは十分に身についたのではないでしょうか。

でも、本当の実力は、学んだことを実際の開発で応用できてこそ発揮されるものです。

そこで、ここからはdocument.createElementを使った応用例をいくつか見ていきましょう。

実際の開発でよく遭遇するシーンを想定して、どのようにdocument.createElementを活用できるか考えてみましょう。

○動的なフォームの生成

Webアプリケーションを作っていると、ユーザーの入力に応じて動的にフォームを生成したいことがあります。

例えば、「もっと入力欄を追加する」ボタンを押すと、新しい入力欄が追加されるようなフォームです。

document.createElementを使えば、このような動的なフォームを簡単に実装できます。

次のサンプルコードを見てみましょう。

<form id="myForm">
  <label for="name">名前:</label>
  <input type="text" id="name" name="name"><br>

  <label for="email">メールアドレス:</label>
  <input type="email" id="email" name="email"><br>

  <button type="button" id="addField">入力欄を追加</button>
</form>
// 「入力欄を追加」ボタンの要素を取得
const addFieldButton = document.getElementById('addField');

// ボタンがクリックされたときの処理
addFieldButton.addEventListener('click', function() {
  // 新しいlabel要素を生成
  const newLabel = document.createElement('label');
  newLabel.textContent = '追加の入力欄:';

  // 新しいinput要素を生成
  const newInput = document.createElement('input');
  newInput.type = 'text';
  newInput.name = 'additional[]';

  // 新しいbr要素を生成
  const newBr = document.createElement('br');

  // 生成した要素をフォームに追加
  const form = document.getElementById('myForm');
  form.insertBefore(newBr, addFieldButton);
  form.insertBefore(newInput, addFieldButton);
  form.insertBefore(newLabel, newInput);
});

このコードでは、「入力欄を追加」ボタンがクリックされたときに、新しいlabel要素、input要素、br要素を生成し、フォームに追加しています。

新しい要素は、ボタンの前に挿入されるようになっています。

実行すると、「入力欄を追加」ボタンを押すたびに、新しい入力欄とラベルがフォームに追加されます。

このように、document.createElementを使えば、ユーザーのアクションに応じて動的にフォームを変更できます。

入力欄の追加だけでなく、削除や並び替えなども同様の手法で実装できるでしょう。

○カスタムコンポーネントの作成

モダンなJavaScript開発では、UIの部品化が重要なトピックの1つです。

再利用可能なUIパーツを作ることで、コードの管理がしやすくなり、開発効率も上がります。

document.createElementを使えば、カスタムコンポーネントを作成し、UIの部品化を実現できます。

次のサンプルコードを見てみましょう。

// カスタムボタンコンポーネントを作成
function createCustomButton(text, onClick) {
  // button要素を生成
  const button = document.createElement('button');
  button.textContent = text;

  // スタイルを設定
  button.style.backgroundColor = '#007bff';
  button.style.color = '#fff';
  button.style.padding = '10px 20px';
  button.style.border = 'none';
  button.style.borderRadius = '5px';
  button.style.cursor = 'pointer';

  // クリックイベントを設定
  button.addEventListener('click', onClick);

  return button;
}

// カスタムボタンを使う
const myButton = createCustomButton('クリックしてね', function() {
  alert('ボタンがクリックされました!');
});

// ボタンをページに追加
document.body.appendChild(myButton);

このコードでは、createCustomButton関数を定義して、カスタムボタンコンポーネントを作成しています。

この関数は、ボタンのテキストとクリックイベントのハンドラを引数として受け取ります。

関数内では、document.createElementを使ってbutton要素を生成し、テキストとスタイルを設定しています。

また、クリックイベントのハンドラを設定して、ボタンがクリックされたときの動作を定義しています。

実行すると、ページ上に、青色の背景色とテキストを持つカスタムボタンが表示されます。

ボタンをクリックすると、アラートが表示されます。

このようなカスタムコンポーネントを作成することで、一貫したデザインのUIパーツを簡単に再利用できます。

ボタンだけでなく、入力欄やカードなどさまざまなコンポーネントを作れるでしょう。

○ライブラリやフレームワークでの活用

document.createElementは、JavaScriptのライブラリやフレームワークでも広く活用されています。

有名なフレームワークの多くは、内部でdocument.createElementを使って、動的にHTMLを生成しているのです。

例えば、Reactというポピュラーなフレームワークでは、仮想DOMという概念を使っています。

仮想DOMは、実際のDOMとは別に、メモリ上に保持されるツリー構造です。

Reactは、この仮想DOMを使って効率的にDOMを更新します。

仮想DOMを構築する際にも、document.createElementと同様の仕組みが使われています。

ここでは、Reactコンポーネントの例を紹介します。

import React from 'react';

function MyComponent() {
  return (
    <div>
      <h1>Hello, World!</h1>
      <p>This is a React component.</p>
    </div>
  );
}

export default MyComponent;

このコードは、JSXと呼ばれる構文で書かれていますが、内部的にはdocument.createElementと同じような処理が行われています。

JSXのタグは、React.createElementという関数に変換され、仮想DOMを構築するために使われるのです。

他にも、VueやAngularなど、多くのフレームワークがdocument.createElementと同様の仕組みを活用しています。

このフレームワークを使う際は、document.createElementの知識が役立つでしょう。

まとめ

document.createElementを使ってHTMLを動的に生成する方法を解説してきました。

新しい要素の作成からフラグメントの活用まで、多彩なテクニックを身につけることができたはずです。

document.createElementを駆使して、よりインタラクティブで魅力的なWebアプリケーションを作っていきましょう。