JavaScript

Find the nearest element (including itself) that matches a CSS selector, often used in event delegation.

closest()

クリックされた場所(子要素)から、目的の要素(ボタン・リンク・カードなど)まで最短でたどるためのメソッド。イベント委譲で「本当の押下対象」を安全に見つけたいときに便利。

このページでできるようになること

closest() とは

要点:closest() は、呼び出した要素から親方向へたどり、指定したCSSセレクタに一致する最も近い要素を返します。自分自身も一致判定の対象です。

基本形

const hit = element.closest('.card'); // Element または null
戻り値
一致した要素(Element)が返ります。見つからなければ null です。
探索の向き
「自分 → 親 → 親…」の方向だけを見ます(子方向は見ません)。
一致判定
CSSセレクタ('button' / '.class' / '[data-x]' など)で判定します。

最小デモ:クリック元からボタンまでたどる(イベント委譲)

ボタンの中にアイコン<span>があると、クリックされた要素は「ボタンの中身」になりがちです。closest('button')で「ボタン本体」まで一発で戻します。

タスクA

カード内のどこを押してもOK。

タスクB

子要素をクリックしても、ボタンを特定できる。

 

JavaScript(closest()でボタンとカードを特定)

const list = document.querySelector('#cardList');
const out = document.querySelector('#out');

list.addEventListener('click', (e) => {
    if (!(e.target instanceof Element)) return;

    const button = e.target.closest('button');
    if (!button) return; // ボタン以外のクリックは無視

    const card = button.closest('.card');
    if (!card) return;

    const action = button.dataset.action;
    const id = card.dataset.id;

    if (action === 'open') {
        out.textContent = `id=${id} を開きます`;
        return;
    }

    if (action === 'delete') {
        out.textContent = `id=${id} を削除します`;
    }
});

ポイント:e.target がアイコンのや絵文字の位置になっても、closest('button')で「意図した要素」まで戻せます。

基本の書き方

1) クリックされた場所から「操作対象」を見つける

JavaScript

container.addEventListener('click', (e) => {
    if (!(e.target instanceof Element)) return;

    const button = e.target.closest('button');
    if (!button) return;

    // button を使って処理する
});

2) 一致しなければ null(必ずガードする)

JavaScript

const card = element.closest('.card');
if (!card) {
    // 見つからない場合の処理(無視、エラー表示など)
    return;
}

3) 「自分自身も判定する」ので、欲しい要素が直で来てもOK

クリック対象がすでに<button>なら、button.closest('button')はそのボタン自身を返します。

事故りやすい仕様ポイント(試験でも狙われる)

closest()は「要素(Element)」のメソッド
documentwindowにはありません。イベントでは基本 e.target は要素ですが、念のため e.target instanceof Element で守ると安全です。
見つからないと null
nullのまま.dataset.classListに触るとエラーになります。if (!hit) return; を先に書きます。
探索は親方向だけ
「子の中から探す」用途は querySelector を使います。
Shadow DOMは突き抜けない
closest()は同じツリー内をたどるため、Shadow DOMの境界を越えて外側の要素を直接見つける用途には向きません(必要ならcomposedPath()などを検討)。
セレクタが不正だと例外
CSSセレクタとして成立しない文字列を渡すとエラーになります(動的に組むときは注意)。

よくある勘違い(間違いパターン)

e.target === button 前提で書いた
❌ ボタン内の子要素がクリックされると成立しません。⭕ e.target.closest('button') を使います。
const card = e.target.closest('.card'); をガードしない
❌ 見つからないと null。⭕ if (!card) return; を先に書きます。
親をたどるために parentElement.parentElement... を直書きした
❌ DOM構造が変わると壊れます。⭕ セレクタで意味を指定できる closest() が堅いです。

実務での使いどころ

A11y / UX の注意

関連API・相互作用

matches()
「この要素がセレクタに一致するか」を真偽値で返す(closest()は一致した要素を返す)。
querySelector()
子孫方向から探す(closest()は親方向)。
parentElement
親要素を1つだけ取る(closest()は繰り返し+一致判定つき)。
Event.target
実際にクリックされた「いちばん内側」の要素。ここからclosest()で操作対象を特定しやすい。

試験で得点できる整理(用語・ひっかけ・ミニ確認)

用語

ひっかけ

ミニ確認

closest() に関するよくある質問

Q. closest() は自分自身も探しますか?
A. はい。呼び出した要素自身がセレクタに一致するなら、その要素が返ります。
Q. 見つからないときは何が返りますか?
A. null です。if (!hit) return; のようにガードします。
Q. closest()querySelector() の違いは?
A. closest()は親方向、querySelector()は子孫方向です。
Q. イベント委譲でなぜ closest() が便利?
A. クリックされた要素(target)が子要素でも、意図したボタンやカードまで一発で戻れるからです。
Q. どのブラウザで使えますか?
A. 現行の主要ブラウザで利用できます(古い環境では非対応の可能性があります)。
Data on support for the Element.closest feature across the major browsers from caniuse.com

症状早見

Cannot read properties of null
closest()nullなのに、その後で.dataset等に触っている。if (!hit) return;を先に入れる。
e.target.closest is not a function
e.targetが要素ではない可能性。if (!(e.target instanceof Element)) return;で守る。
想定と違う要素が取れる
セレクタが広すぎる可能性(例:'div')。意味のあるクラスや属性('.card' / [data-action])にする。

まとめ