この記事の前提条件
対象: jQuery(既存のjQuery環境での実装を想定)
難易度: ★★☆
所要時間: 約5分
検索窓の候補一覧や、ハンバーガーメニューを開いた時、ポップアップの外側をクリックしたら自動で閉じてほしいのは、ユーザーからすると当たり前の挙動です。実装の考え方自体はシンプルですが、書き方を間違えると開いた瞬間に閉じてしまう、というつまずきが起きやすい機能でもあります。
基本の考え方: クリックされた場所が対象の外かどうかを判定する
$(document).on('click', function(e) {
if (!$(e.target).closest('.popup').length) {
$('.popup').removeClass('is-active');
}
});closest('.popup')は、「クリックされた要素自身か、その親をたどっていった先に.popupが見つかるか」を調べています。見つからない(.lengthが0)場合は「ポップアップの外側がクリックされた」と判断できるので、閉じる処理を実行します。
⚠️ 開くボタンのクリックまで拾って一瞬で閉じてしまう問題
この機能で一番よくあるつまずきが、「ポップアップを開くボタン自体のクリック」までdocumentのクリックイベントが拾ってしまい、開いた瞬間に外側クリック判定されて即座に閉じてしまう、という現象です。原因は、ボタンをクリックした時に「ポップアップを開くイベント」と「documentのクリックイベント(閉じる判定)」が同じタイミングで両方発火してしまうことです。
解決法: 開くボタンも判定対象に含める
「ポップアップの中」だけでなく「開くボタン自体」もクリック対象として除外することで解決します。
$(document).on('click', function(e) {
if (
!$(e.target).closest('.popup').length &&
!$(e.target).closest('.popup-open-btn').length
) {
$('.popup').removeClass('is-active');
}
});「ポップアップの中でもなく、開くボタンでもない場所がクリックされた時だけ閉じる」という条件にすることで、開いた瞬間に閉じてしまう不具合を防げます。
まとめ
closest()で「クリック位置がポップアップの中かどうか」を判定する- 開くボタン自体も判定に含めないと、開いた瞬間に閉じてしまう不具合が起きる
- 「ポップアップの中でも開くボタンでもない場所」という条件で判定するのが安全