9/7まで 最大30%OFF 初心者編|無料コーディング教材|HTML・CSS・jQueryを実践で学ぶ

jQueryのclickイベントの使い方|on()・動的要素・アコーディオンを初心者向けに解説

jQuery clickの使い方を示すアイキャッチ

ボタンをクリックしたら文章を変えたい、メニューを開きたいと思っても、「clickとon(‘click’)のどちらを使うの?」「追加したボタンだけ反応しない」と迷うことがありますよね。

jQueryでクリック処理を設定するときは、.on('click', handler)を使います。以前よく使われた.click(handler)は非推奨です。

$('#target-button').on('click', function () {
  // クリックされたときの処理
});

この記事では、クリック回数の表示、あとから追加した要素へのイベント委譲、FAQアコーディオンを実際に動かしながら、クリックイベントの使い方と動かない原因を解説します。

jQueryのclickイベントとは

clickは、要素がクリック操作で有効化されたときに発生するイベントです。処理を登録しておくと、ボタンを押したあとに文章の変更、クラスの追加、メニューの開閉などを実行できます。

次の図は、ボタン操作から処理が実行されるまでの流れです。

ボタンのクリックから処理を実行するまでの流れ

<button>へclickイベントを設定すると、マウスやタッチだけでなく、フォーカスした状態でEnterキーやSpaceキーを押した操作にもブラウザが対応します。クリックできる部品は、見た目だけの<div>ではなく<button type="button">で作りましょう。

clickイベントの基本構文

.on()の第1引数にイベント名'click'、第2引数に実行したい関数を指定します。

$('セレクタ').on('click', function (event) {
  // クリックされたときの処理
});

eventには、クリックされた場所や対象要素などのイベント情報が入ります。function内のthisは、処理の対象になった要素です。

$('.action-button').on('click', function (event) {
  console.log($(this).text());
  console.log(event.type); // click
});

click()ではなくon(‘click’)を使う

.click(handler)はjQuery 3.3で非推奨になりました。現在のコードは.on('click', handler)で記述します。

// 非推奨の短縮形
$('#target-button').click(function () {
  console.log('クリックされました');
});

// 推奨する書き方
$('#target-button').on('click', function () {
  console.log('クリックされました');
});

.on()なら、イベント委譲、複数イベント、名前空間による解除なども同じ形式で扱えます。既存の.click()が直ちに動かなくなるとは限りませんが、新しく書くコードは.on()へ統一するのが分かりやすいでしょう。

ボタンのクリック回数を表示する

最初に、ボタンを押すたびに数値を1ずつ増やす基本例を作ります。実際に2回クリックした表示が次の画像です。

ボタンを2回クリックして回数を表示した画面

HTMLでボタンと結果欄を作る

index.htmlへボタンと結果欄を配置します。ボタンのtype="button"は、フォーム内に置いた場合の意図しない送信を防ぐための指定です。

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>クリック回数を表示する例</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <main class="demo">
      <p class="demo__label">基本のクリックイベント</p>
      <h1>ボタンを押すと回数が増えます</h1>
      <p class="lead">クリックされたボタンの処理をjQueryで実行します。</p>
      <button id="count-button" type="button">クリックする</button>
      <p id="count-result" class="result" aria-live="polite">クリック回数:0回</p>
    </main>

    <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>

aria-live="polite"を付けると、数値が変わったことをスクリーンリーダーなどの支援技術へ穏やかに伝えられます。

JavaScriptで数値を更新する

script.jsでは、クリック回数を保存する変数を用意します。クリックされるたびに1を加え、.text()で結果欄を更新します。

let clickCount = 0;

$('#count-button').on('click', function () {
  clickCount += 1;
  $('#count-result').text(`クリック回数:${clickCount}回`);
});

clickCountを関数の外へ置くことで、前回までの回数を保持できます。ページを再読み込みすると変数は0へ戻ります。

あとから追加した要素をクリックできるようにする

ページ表示後に追加されたボタンへ直接イベントを設定しても、追加前の時点では対象要素が存在しません。この場合は、すでに存在する親要素へイベントを設定する「イベント委譲」を使います。

次の例では「項目を追加」を押して作られた項目2もクリックに反応しています。

あとから追加した項目をイベント委譲で選択した画面

index.htmlには、追加ボタン、項目を入れる#item-list、結果欄を用意します。

<main class="demo">
  <p class="demo__label">イベント委譲の例</p>
  <h1>あとから追加した項目も反応します</h1>
  <p class="lead">項目を追加してから、追加された項目をクリックしてください。</p>

  <button id="add-button" type="button">項目を追加</button>
  <div id="item-list" class="item-list">
    <button class="item-button" type="button">項目1</button>
  </div>
  <p id="dynamic-result" class="result" aria-live="polite">
    項目を選択してください。
  </p>
</main>

script.jsでは、#item-listへclickイベントを設定し、第2引数に実際の対象である.item-buttonを指定します。

let itemCount = 1;

$('#add-button').on('click', function () {
  itemCount += 1;
  const $button = $('<button>')
    .addClass('item-button')
    .attr('type', 'button')
    .text(`項目${itemCount}`);

  $('#item-list').append($button);
});

$('#item-list').on('click', '.item-button', function () {
  $('.item-button').removeClass('is-selected');
  $(this).addClass('is-selected');
  $('#dynamic-result').text(`${$(this).text()}を選択しました。`);
});

子要素で発生したclickイベントは親要素へ伝わります。この「イベント伝播」を利用するため、あとから追加されたボタンでも#item-listがクリックを受け取り、対象が.item-buttonなら処理を実行できます。

イベント委譲の親要素は、対象を含む最も近い固定要素にします。ページ全体のdocumentへ何でも登録するより、#item-listへ限定したほうが処理を追いやすくなります。

項目の追加に使っているappend()は、次の記事で詳しく解説しています。

クリックで開くFAQアコーディオンを作る

clickイベントの実用例として、質問を押すと回答が開くFAQを作ります。質問部分を<button>にすると、キーボードでも操作できます。

クリックで回答を開いたFAQアコーディオンの画面

HTMLで質問と回答を関連付ける

aria-controlsには開閉する回答のidを指定します。aria-expandedは閉じているときfalse、開いているときtrueへ変更します。

<main class="demo">
  <p class="demo__label">クリックイベントの活用例</p>
  <h1>FAQアコーディオン</h1>
  <p class="lead">質問をクリックすると回答が開きます。</p>

  <div class="accordion">
    <div class="accordion__item">
      <button
        class="accordion__button"
        type="button"
        aria-expanded="false"
        aria-controls="answer-1"
      >
        <span>jQueryはどこに読み込みますか?</span>
        <span aria-hidden="true">+</span>
      </button>
      <div id="answer-1" class="accordion__panel" hidden>
        jQuery本体を先に読み込み、その後に自分のJavaScriptを読み込みます。
      </div>
    </div>
  </div>
</main>

クリック時に回答の表示を切り替える

script.jsで現在のaria-expandedを確認し、反対の状態へ切り替えます。回答のhiddenプロパティも同時に更新します。

$('.accordion__button').on('click', function () {
  const $button = $(this);
  const panelId = $button.attr('aria-controls');
  const $panel = $(`#${panelId}`);
  const isOpen = $button.attr('aria-expanded') === 'true';

  $button.attr('aria-expanded', String(!isOpen));
  $button.find('[aria-hidden="true"]').text(isOpen ? '+' : '−');
  $panel.prop('hidden', isOpen);
});

開閉状態を見た目だけでなくaria-expandedでも伝えると、支援技術からも状態を確認できます。プラス・マイナス記号にはaria-hidden="true"を付け、装飾として扱っています。

複数項目やアニメーションを含むアコーディオンは、次の記事で詳しく解説しています。

3つの例で使うCSS

表示画像では、次のCSSを共通で使っています。style.cssへ記述すると、カード、ボタン、結果欄、アコーディオンの見た目を再現できます。

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 40px 20px;
  color: #172033;
  background: #f2f6fc;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.demo {
  width: min(760px, 100%);
  margin: 0 auto;
  padding: 36px;
  border: 1px solid #d9e2ef;
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 16px 40px rgb(41 70 115 / 10%);
}

.demo__label {
  margin: 0 0 8px;
  color: #2468d8;
  font-weight: 700;
}

h1 {
  margin: 0 0 12px;
  font-size: clamp(28px, 5vw, 40px);
}

.lead {
  margin: 0 0 26px;
  color: #536079;
}

button {
  padding: 12px 20px;
  border: 0;
  border-radius: 10px;
  color: #fff;
  background: #2468d8;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

button:hover {
  background: #1855b7;
}

button:focus-visible {
  outline: 4px solid rgb(36 104 216 / 25%);
  outline-offset: 3px;
}

.result {
  margin: 22px 0 0;
  padding: 18px;
  border-left: 6px solid #24a46d;
  border-radius: 10px;
  color: #176b4b;
  background: #eefaf5;
  font-weight: 700;
}

.item-list,
.accordion {
  display: grid;
  gap: 12px;
  margin-top: 22px;
}

.item-button,
.accordion__button {
  width: 100%;
  color: #172033;
  background: #eef4ff;
  text-align: left;
}

.item-button.is-selected {
  color: #fff;
  background: #2468d8;
}

.accordion__button {
  display: flex;
  justify-content: space-between;
}

.accordion__panel {
  padding: 18px;
  border-left: 4px solid #2468d8;
  background: #f8faff;
}

.accordion__panel[hidden] {
  display: none;
}

@media (max-width: 560px) {
  body {
    padding: 20px 12px;
  }

  .demo {
    padding: 24px 18px;
  }
}

リンクのクリックを処理する

リンクには「指定URLへ移動する」という既定動作があります。クリック後にページを移動させたくない場合は、イベントのpreventDefault()を呼び出します。

$('.modal-link').on('click', function (event) {
  event.preventDefault();
  $('#modal').removeAttr('hidden');
});

単に処理を実行するだけならリンクではなくボタンを使います。別ページへ移動する意味があるときだけ<a href="...">を選びましょう。

クリックをJavaScriptから実行する

.trigger('click')を使うと、登録済みのclick処理をJavaScriptから実行できます。テストや、別の操作から同じ処理を呼びたい場合に利用します。

$('#target-button').on('click', function () {
  console.log('クリック処理を実行しました');
});

$('#target-button').trigger('click');

非推奨の引数なし.click()で発火させるのではなく、目的が明確な.trigger('click')を使ってください。

clickが動かない・2回動くときの確認ポイント

HTMLより先にイベントを設定している

対象要素が作られる前に$('#target-button')を実行すると、イベントを設定できません。script.js</body>直前で読み込むか、DOMの準備後に実行します。

$(function () {
  $('#target-button').on('click', function () {
    console.log('クリックされました');
  });
});

セレクタが一致していない

id="target-button"$('#target-button')class="target-button"$('.target-button')で選択します。#.を取り違えていないか確認してください。

あとから追加した要素へ直接設定している

動的に追加する要素には、先に存在する親要素からイベント委譲します。$('#item-list').on('click', '.item-button', handler)の形を使いましょう。

同じイベントを複数回登録している

クリック1回で処理が2回動く場合は、script.jsを重複して読み込んでいないか、同じ初期化関数を繰り返し実行していないか確認します。

再初期化が必要な部品では、イベント名に名前空間を付けてから解除・再登録すると重複を防げます。

$('#target-button')
  .off('click.counter')
  .on('click.counter', function () {
    console.log('1回だけ実行します');
  });

親と子の両方に処理がある

clickイベントは子要素から親要素へ伝播します。親と子の両方にイベントがあると、両方の処理が実行されます。まずは意図した動きか確認し、必要な場合だけevent.stopPropagation()で親への伝播を止めます。

矢印関数でthisを使っている

変更対象をthisで取得する場合はfunction () {}を使います。矢印関数を使う場合はevent.currentTargetから取得してください。

$('#target-button').on('click', (event) => {
  $(event.currentTarget).addClass('is-active');
});

.on()の仕組みや解除方法を詳しく確認したい場合は、次の記事も参考にしてください。

jQueryのclickについてよくある質問

クリック処理を1回だけ実行できますか?

.one('click', handler)を使うと、最初の1回だけ処理を実行し、その後は自動でイベントが解除されます。

$('#welcome-button').one('click', function () {
  console.log('最初の1回だけ表示します');
});

ダブルクリックを検知できますか?

.on('dblclick', handler)で検知できます。ただし、スマートフォンでは操作が分かりにくく、誤操作も起こりやすいため、重要な操作は通常のクリックで実行できる設計がおすすめです。

buttonとdivのどちらへ設定すればよいですか?

ユーザーが操作する部品には<button>を使います。ブラウザ標準のキーボード操作とフォーカスを利用でき、役割も支援技術へ伝わります。

まとめ

jQueryでクリック処理を設定するときは、非推奨の.click()ではなく.on('click', handler)を使います。処理内のthisevent.currentTargetから、対象要素を取得できます。

あとから追加する要素には、近い固定の親要素からイベント委譲します。操作部品を<button>で作り、フォーカス表示やaria-expandedも整えると、マウス以外でも使いやすいクリック処理になります。