JavaScriptで要素の親要素を取得するには、parentElement・parentNode・closest() を使います。それぞれの違いと使い分けを解説します。
parentElement が基本です。parentNode とほぼ同じで、違いが出るのは最上位(<html>)のときだけ。「特定の祖先」までさかのぼるなら closest("セレクタ") が便利です。parentElementで親要素を取得する(基本)
parentElement は、その要素のすぐ上の親要素を返します。取得した親要素は、そのまま操作できます。
const child = document.getElementById("child");
const parent = child.parentElement;
console.log(parent); // 親要素
parent.classList.add("active"); // そのまま操作できる
parentNodeとの違い(最上位でのみ差が出る)
parentNode も親を返し、ほとんどの場合 parentElement と同じ結果になります。違いが出るのはたどり着く先が要素ではないときだけです。
parentElement:親が要素なら返す。要素でなければnullparentNode:親のノードを返す(documentなども含む)
const html = document.documentElement; // <html> console.log(html.parentNode); // document(ノード) console.log(html.parentElement); // null(documentは要素ではない)
parentNode はテキストノードを返す」というのは誤りです。要素の親がテキストノードになることはありません(テキストノードは子を持てないため)。実際の違いは、最上位の <html> で parentNode が document を返し、parentElement が null を返す点です。通常は parentElement を使えば十分です。closestで「特定の祖先」を取得する(実用)
実務でよくあるのは「クリックされた要素から、特定のカード(祖先)を取得したい」というケースです。parentElement を何度もたどる代わりに、closest("セレクタ") を使うと条件に合う最も近い祖先を一発で取得できます。
// <div class="card"> ... <button class="btn"> ... の構造で
const btn = document.querySelector(".btn");
// btnから見て最も近い .card を取得(自分自身も対象)
const card = btn.closest(".card");
console.log(card); // 該当する祖先。無ければ null
closest() はイベント委譲(親で受けて event.target.closest() で判定)でも頻出します。セレクタの書き方はquerySelectorの使い方と同じです。
実践:イベント委譲でclosestを使う(動くデモ)
closest() が最も活躍するのがイベント委譲です。子要素1つずつにリスナーを付ける代わりに、親に1つだけリスナーを置き、event.target.closest() で「どの項目が押されたか」を特定します。項目が動的に増減しても対応でき、リスナーも1つで済みます。
// 親(リスト)に1つだけリスナーを置く
document.getElementById("list").addEventListener("click", (e) => {
const btn = e.target.closest(".delete-btn");
if (!btn) return; // ボタン以外のクリックは無視
const item = btn.closest(".item"); // 押されたボタンが属する item を取得
item.remove(); // その item を削除
});
↓ 各カードのボタンを押すと、closest(".card") で親カードを特定してハイライトします:
ボタンを増やしてもリスナーは1つのまま動きます。これがイベント委譲+closest() の強みです。
さらに上の階層へたどる
2つ上の親なら parentElement をつなげます。ただし階層が深いと壊れやすいので、可能なら closest() でセレクタ指定するのが安全です。
// 2つ上の親(構造変更に弱い)
const grandParent = child.parentElement.parentElement;
// セレクタで指定(構造が多少変わっても動く・推奨)
const section = child.closest("section");
逆に子要素を取得する方法はHTMLの子要素を取得する方法(children・childNodes・querySelectorAll)、親要素内に絞った検索はquerySelectorAllで取得した複数要素を操作する方法を参考にしてください。
よくある質問(FAQ)
parentElement で十分です。両者は通常同じ結果を返し、違いが出るのは最上位の <html> のとき(parentNode は document、parentElement は null)だけです。element.closest("セレクタ") を使います。条件に合う最も近い祖先を返し、無ければ null です。parentElement を何度もたどるより安全で読みやすくなります。parent.querySelectorAll(".target") のように、親要素を起点に検索します。document 全体ではなく特定のコンポーネント内に絞れます。closest() は自分自身からさかのぼって判定するため、自分自身がセレクタに一致すれば自分自身を返します。click リスナーを置き、event.target.closest(".item") で「クリックされた要素が属する項目」を特定します。子要素ごとにリスナーを付けずに済み、項目が動的に増減しても対応できます。まとめ
親要素の取得は、すぐ上の親なら parentElement が基本です。parentNode とは最上位(<html>)でのみ結果が変わります(テキストノードを返すというのは誤解です)。
特定の祖先までさかのぼるなら closest("セレクタ") が便利で安全です。イベント委譲でも頻出するので、あわせて覚えておきましょう。
