20
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

タッチパッドとマウスでclickイベントの挙動が変わる理由

Last updated at Posted at 2025-12-15

概要

次のようなUIを実装しました。

  • inputにfocus → ドロップダウン表示
  • optionを選択 → inputに値を反映
  • inputがblur → ドロップダウン非表示

このUIにおいて、

  • マウス操作では正常に動作する
  • タッチパッド操作ではoptionのclickが反映されない

という差が発生しました。

本記事では、イベントの発火順とタイミングに絞って、原因と解決策を説明します。

実装していたUI(簡略)

input.addEventListener('focus', () => {
  dropdown.style.display = 'block';
});

input.addEventListener('blur', () => {
  setTimeout(() => {
    dropdown.style.display = 'none';
  }, 200);
});

option.addEventListener('click', () => {
  input.value = hoge;
  dropdown.style.display = 'none';
});

なぜclickが失敗するのか

clickは「遅いイベント」

clickは、次の操作がすべて完了した後に発火します。

pointerdown / mousedown
↓
pointerup / mouseup
↓
click

一方で、blurはフォーカスが外れた瞬間に即座に発火します。

イベント順の違い

マウス操作(多くの環境)

mousedown
↓
mouseup
↓
click
↓
blur

clickが先に処理されるため問題にならない。

タッチパッド操作(発生しうるケース)

pointerdown
↓
blur
↓
pointerup
↓
click

👉 clickより前にblurが発火するケースがある

タッチパッドでclickが効かないパターン

  1. optionを押す
  2. pointerdown時点でinputのフォーカスが外れる
  3. blurによりドロップダウンが閉じられる
  4. clickが発火する頃にはDOMが消えている

結果として、clickが「効かない」ように見える。

※ これはバグではなく、clickとblurの発火順が仕様で保証されていないことによる挙動です。

解決策:pointerdownを使う

option.addEventListener('pointerdown', (event) => {
  input.value = hoge;
  dropdown.style.display = 'none';
});

なぜpointerdownで解決するのか

  • clickblurより前に発火する
  • フォーカスが切れる前に処理できる

そのため、タッチパッド・マウス両方で安定した挙動になります。

20
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?