Web制作でJavaScriptを使い始めると、「ボタンを押したらリストの最後に項目を追加したい」「特定の要素の手前にメッセージを差し込みたい」「不要になったモーダルや要素を画面から消したい」といったDOM操作が必要になります。

しかし、いざ実装しようとすると「append() と before() はどこに入るのか」「appendChild() とは何が違うのか」など、挿入位置やメソッドの使い分けで迷ってしまいがちです。

この記事では、現代のJavaScriptで標準的に使われるDOM操作メソッド(append / prepend / before / after / replaceWith / remove)の挿入位置の違いを視覚的に整理し、それぞれの使い方や注意点をわかりやすく解説します。

まずは要素を追加・削除・入れ替える方法の違いを確認

まずは、各メソッドが「何を対象にして」「どこに作用するのか」の一覧です。

メソッド 主な動作 挿入・変更される場所 基準となる要素
append() 追加 親要素の 一番最後(末尾) 親要素
prepend() 追加 親要素の 一番最初(先頭) 親要素
before() 追加 対象要素の 直前(手前) 兄弟要素(対象要素)
after() 追加 対象要素の 直後(後ろ) 兄弟要素(対象要素)
replaceWith() 入れ替え 対象要素 そのものを置換 置き換えたい要素
remove() 削除 対象要素 そのものを削除 削除したい要素

これをDOMツリーの構造として見ると、以下のようになります。

[親要素]
 │
 ├─ prepend()   ← 親要素の内側:先頭に追加
 │
 ├─ [要素A]
 ├─ before()    ← [対象要素] の直前(外側・兄弟)
 ├─ [対象要素]
 ├─ after()     ← [対象要素] の直後(外側・兄弟)
 ├─ [要素B]
 │
 └─ append()    ← 親要素の内側:末尾に追加

「親要素の内側 に入れる(append / prepend)」のか、「特定の要素の前や後ろ に並べる(before / after)」のかを区別することが、迷わないための第一歩です。

JavaScriptで新しい要素を作る

要素を追加する前に、まずJavaScript側で挿入するための要素を生成します。

// 1. 新しい <li> 要素をメモリ上に作成する
const item = document.createElement('li');

// 2. 要素の中にテキストを設定する
item.textContent = '新しい項目';

ここで初心者が最も見落としやすいのが、「document.createElement() を実行しただけでは、画面には一切表示されない」 という点です。

createElement() は、ブラウザのメモリ上に要素のオブジェクトを作ったに過ぎません。

このあと紹介する append() などのメソッドを使って、HTMLのDOMツリー上のどこかに挿入して初めて画面に描画されます。

append()で親要素の最後に追加する

最もよく使われるのが、親要素の内側の一番最後に子要素を追加する append() です。

<ul class="js-list">
  <li>項目1</li>
</ul>
const list = document.querySelector('.js-list');

const item = document.createElement('li');
item.textContent = '項目2(末尾)';

// 親要素の末尾に挿入
list.append(item);

実行後のHTML:

<ul class="js-list">
  <li>項目1</li>
  <li>項目2(末尾)</li>
</ul>

既存の子要素の後ろに、順番通り新しい要素を付け足したい場合は append() を選びます。

prepend()で親要素の最初に追加する

親要素の内側の一番最初(先頭)に子要素を追加したい場合は、prepend() を使います。

const list = document.querySelector('.js-list');

const item = document.createElement('li');
item.textContent = '項目0(先頭)';

// 親要素の先頭に挿入
list.prepend(item);

実行後のHTML:

<ul class="js-list">
  <li>項目0(先頭)</li>
  <li>項目1</li>
  <li>項目2(末尾)</li>
</ul>

「新着のお知らせをリストの一番上に追加したい」「最新のログを先頭に表示したい」といった場面に適しています。

before()とafter()で特定要素の前後に追加する

append() や prepend() は「親要素」を基準にしてその内側へ挿入しましたが、before() と after() は 「DOM上の特定の要素」を基準にして、その直前・直後へ兄弟要素として挿入 します。

<ul>
  <li>項目1</li>
  <li class="target">基準の項目2</li>
  <li>項目3</li>
</ul>
const target = document.querySelector('.target');

// 直前に挿入する要素
const prevItem = document.createElement('li');
prevItem.textContent = '項目1.5(直前)';
target.before(prevItem);

// 直後に挿入する要素
const nextItem = document.createElement('li');
nextItem.textContent = '項目2.5(直後)';
target.after(nextItem);

実行後のHTML:

<ul>
  <li>項目1</li>
  <li>項目1.5(直前)</li>
  <li class="target">基準の項目2</li>
  <li>項目2.5(直後)</li>
  <li>項目3</li>
</ul>

親要素を取得しなくても、対象の要素(target)さえ取得できていれば直接その前後に要素を差し込めるのが大きな特徴です。

replaceWith()で要素を入れ替える

既存の要素を丸ごと別の要素に差し替えたいときは、replaceWith() を使用します。

<div class="old-box">古いコンテンツ</div>
const oldBox = document.querySelector('.old-box');

// 置き換える新しい要素を作成
const newBox = document.createElement('div');
newBox.className = 'new-box';
newBox.textContent = '差し替え後のコンテンツ';

// 要素そのものを置き換える
oldBox.replaceWith(newBox);

実行後のHTML:

<div class="new-box">差し替え後のコンテンツ</div>

innerHTML や textContent のように「要素の中身を書き換える」のではなく、そのHTML要素自体を別の要素へごっそりバトンタッチする操作になります。

remove()で要素を削除する

不要になった要素をDOM上から消去したい場合は、削除したい要素に対して remove() を実行します。

<ul class="list">
  <li>項目1</li>
  <li class="js-delete-target">削除される項目</li>
</ul>
const target = document.querySelector('.js-delete-target');

// 対象要素をDOMから削除
target.remove();

以前から使われているコードでは target.parentNode.removeChild(target) という親要素を経由した書き方が必要でしたが、現在のブラウザ環境では、target.remove() だけで簡潔に削除できます。

クリックされたリスト項目をその場で削除する実践的なコードや、動的に追加された要素の削除管理については、以下の記事で詳しく解説しています。

参照:後から追加した要素でclickイベントが動かない原因|イベントデリゲーションの使い方

ここまで紹介したDOM操作は、下のCodePenで実際に試せます。各ボタンを押して、要素がどこに追加・削除・入れ替えられるのか確認してみてください。

完成コードは下のCodePenでも確認できます。HTML、CSS、JavaScriptを切り替えながら、ボタンを押したときにどこが変わるのか見てみてください。

See the Pen Web制作JS|DOM操作|要素の追加・削除・入れ替えサンプル by WebToolGen (@webtoolgen) on CodePen.

append()とappendChild()は何が違う?

要素を追加する方法を調べていると、昔から使われている appendChild() もよく目にします。

どちらを使うべきか迷いやすい部分ですが、仕様上の違いは以下の通りです。

比較項目 append() appendChild()
Nodeオブジェクトの追加 対応(可能) 対応(可能)
テキスト文字列の直接追加 対応(自動でTextノード化) 非対応(エラーになる)
複数の要素・ノードの同時追加 対応(カンマ区切りで複数指定可能) 非対応(1度に1つのみ)
メソッドの戻り値 undefined 追加された Node

append() は比較的新しく策定されたメソッドで、以下のように複数の要素や文字列をまとめて渡すことができます。

// appendなら複数の要素やテキストを一度に末尾へ追加可能
list.append(item1, item2, '追加のテキスト');

Elementへ子要素を追加する一般的な場面では、複数要素や文字列も扱える append() をまず候補にすると分かりやすいでしょう。

一方、追加したNodeを戻り値として使いたい場合などは appendChild() も選択肢になります。

append()にHTML文字列を渡してもHTMLタグとしては描画されない

初心者が非常によく遭遇する落とし穴の1つが、「append() にHTMLタグを含んだ文字列を渡してしまう」パターンです。

const list = document.querySelector('.list');

// ✕ HTMLタグのつもりで文字列を渡してしまう
list.append('<li>新しい項目</li>');

append() に文字列を渡した場合、その文字列はHTMLとして解析されず、Textノードとして挿入されます。

そのため、<li> などのタグを書いても要素にはならず、画面に <li>新しい項目</li> という文字列がそのままテキストとして表示 されます。

<button> や <li> などのHTML文字列をそのままDOM要素として一括挿入したい場合は、createElement ではなく insertAdjacentHTML() などのAPIを使用します。

// ◯ HTML文字列を解釈して末尾に要素として挿入する
list.insertAdjacentHTML('beforeend', '<li>新しい項目</li>');

なお、insertAdjacentHTML() は文字列をHTMLとして解析するため、ユーザー入力や外部から取得した未検証の文字列をそのまま渡すとXSSの原因になります。

内容が信頼できない場合は、createElement() や textContent などを使って組み立てる方法を検討してください。

既にDOM上にある要素をappendすると「コピー」ではなく「移動」する

「画面にある特定の要素を、別のエリアにも表示させたい」と考え、すでにDOM上に存在している要素を取得して別の親要素に append() した場合の挙動にも注意が必要です。

<ul class="list-a">
  <li class="item">移動する項目</li>
</ul>

<ul class="list-b">
  <!-- ここへ入れたい -->
</ul>
const item = document.querySelector('.item');
const listB = document.querySelector('.list-b');

// すでに list-a にある要素を list-b へ append する
listB.append(item);

この処理を実行した結果、item は「list-a に残ったまま list-b にも増える(複製)」のではなく、「list-a から消えて list-b へ場所を移動する(移動)」 という動作になります。

DOMツリーにおいて、1つの実体ノードが同時に2箇所の親を持つことはできません。

もし元の要素を残したまま増やしたい場合は、cloneNode() メソッドを使って要素を複製してから挿入する必要があります。

// 複製してから追加したい場合
const cloneItem = item.cloneNode(true);
listB.append(cloneItem);

※ cloneNode(true) の true は子要素まで含めて複製する指定です。

addEventListener() で登録したイベントリスナーまで複製されるわけではありません。

また、id 属性を持つ要素を複製する場合は、同じ id がページ内に重複しないよう注意してください。

要素の追加・削除がうまくいかないときの確認方法

意図通りに要素が追加・削除されない場合は、以下のステップ順にコンソールで状態を確認します。

1. 基準となる要素が取得できているか

console.log('親要素:', list);
console.log('基準要素:', target);

追加先の親要素や、before() / after() の基準となる要素が null になっていると、その後の操作はすべてエラーになります。

参照:querySelectorで要素を取得できない・nullになる原因と確認方法

2. createElementした要素をDOMへ挿入しているか

コードの最後で parent.append(item) や target.before(item) などの挿入処理を呼び忘れていないか確認します。

3. append()とbefore() / after()の基準を混同していないか

どの要素に対してメソッドを呼んでいるかを確認します。

list.append(item);   // itemはlistの子要素として末尾に追加される
target.before(item); // itemはtargetと同じ階層の兄弟要素として直前に追加される

「どの要素の内側へ入れたいのか」「どの要素の前後へ並べたいのか」を確認すると切り分けやすくなります。

4. HTML文字列がそのまま画面に出ていないか

HTMLタグの文字列を append() に直接渡していないか確認します。

文字列をHTMLとして挿入する必要がある場合は insertAdjacentHTML() などを使用しますが、ユーザー入力や外部データを扱う場合は、createElement() や textContent で組み立てる方法も検討してください。

まとめ

JavaScriptによる要素の追加・削除・入れ替えは、「どの要素を基準にして、どの位置に動かすか」 を整理することが大切です。

  • 親の末尾に追加:parent.append(element)
  • 親の先頭に追加:parent.prepend(element)
  • 基準要素の直前に追加:target.before(element)
  • 基準要素の直後に追加:target.after(element)
  • 要素そのものを入れ替え:target.replaceWith(newElement)
  • 要素そのものを削除:target.remove()

それぞれの位置関係のイメージを頭に入れて、目的のUIに最適なメソッドを使い分けてみてください。