タスクA
カード内のどこを押してもOK。
Find the nearest element (including itself) that matches a CSS selector, often used in event delegation.
クリックされた場所(子要素)から、目的の要素(ボタン・リンク・カードなど)まで最短でたどるためのメソッド。イベント委譲で「本当の押下対象」を安全に見つけたいときに便利。
element.closest(selector) の戻り値(要素 or null)を説明できるclosest() が「自分自身も判定する」仕様を踏まえて実装できるnull 対策(見つからない場合のガード)を書けるtarget / イベント委譲 / セレクタのひっかけを判断できる要点:closest() は、呼び出した要素から親方向へたどり、指定したCSSセレクタに一致する最も近い要素を返します。自分自身も一致判定の対象です。
基本形
const hit = element.closest('.card'); // Element または null
Element)が返ります。見つからなければ null です。'button' / '.class' / '[data-x]' など)で判定します。ボタンの中にアイコンや<span>があると、クリックされた要素は「ボタンの中身」になりがちです。closest('button')で「ボタン本体」まで一発で戻します。
カード内のどこを押してもOK。
子要素をクリックしても、ボタンを特定できる。
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')で「意図した要素」まで戻せます。
JavaScript
container.addEventListener('click', (e) => {
if (!(e.target instanceof Element)) return;
const button = e.target.closest('button');
if (!button) return;
// button を使って処理する
});
null(必ずガードする)JavaScript
const card = element.closest('.card');
if (!card) {
// 見つからない場合の処理(無視、エラー表示など)
return;
}
クリック対象がすでに<button>なら、button.closest('button')はそのボタン自身を返します。
closest()は「要素(Element)」のメソッドdocumentやwindowにはありません。イベントでは基本 e.target は要素ですが、念のため e.target instanceof Element で守ると安全です。nullnullのまま.datasetや.classListに触るとエラーになります。if (!hit) return; を先に書きます。querySelector を使います。closest()は同じツリー内をたどるため、Shadow DOMの境界を越えて外側の要素を直接見つける用途には向きません(必要ならcomposedPath()などを検討)。e.target === button 前提で書いたe.target.closest('button') を使います。const card = e.target.closest('.card'); をガードしないnull。⭕ if (!card) return; を先に書きます。parentElement.parentElement... を直書きしたclosest() が堅いです。closest()で押されたアイテムを特定する。<button>や<a>で作るのが基本)。.cardや[data-id]までたどって、IDを拾って処理する。<button> / <a> を使う(キーボード操作と役割が自然に揃う)。divにクリックを付ける場合でも、フォーカス・Enter/Spaceの操作・ロールなどを考える(ただしまずはボタン化が安全)。aria-live を使うと変化が伝わりやすい。matches()closest()は一致した要素を返す)。querySelector()closest()は親方向)。parentElementclosest()は繰り返し+一致判定つき)。Event.targetclosest()で操作対象を特定しやすい。'.class' / '#id' / 'button' / '[data-x]' など。closest()は「自分自身も判定する」null(undefined ではない)e.targetがアイコンでも、ボタンまで戻るには? → e.target.closest('button')if (!hit) return;closest() は自分自身も探しますか?null です。if (!hit) return; のようにガードします。closest() と querySelector() の違いは?closest()は親方向、querySelector()は子孫方向です。closest() が便利?target)が子要素でも、意図したボタンやカードまで一発で戻れるからです。
Cannot read properties of nullclosest()がnullなのに、その後で.dataset等に触っている。if (!hit) return;を先に入れる。e.target.closest is not a functione.targetが要素ではない可能性。if (!(e.target instanceof Element)) return;で守る。'div')。意味のあるクラスや属性('.card' / [data-action])にする。closest()は「自分→親方向」に最短一致の要素を返す(見つからなければnull)target からボタンやカードまで戻すのに強いnullガードと「自分自身も判定」の仕様を押さえる