【jQuery】指定した要素にフォーカスを当てる完全ガイド|focus()・tabindex・非表示要素・自動フォーカス・アクセシビリティまで

jQueryの focus() メソッドを使うと、プログラムで特定の入力欄にフォーカスを移動できます。モーダルを開いたときに自動で入力欄を選択したり、バリデーションエラー後に問題のある欄にフォーカスを移したりする実装で重要です。この記事では基本的なfocus()・tabindexの使い方・非表示要素へのフォーカス・フォーカス制御のアクセシビリティまで解説します。

この記事でわかること

  • focus() で要素にフォーカスを当てる基本
  • tabindex を使って通常はフォーカスできない要素をフォーカス可能にする
  • モーダル開閉時のフォーカス管理
  • フォーカスイベント(focus / blur / focusin / focusout)の使い分け
  • フォーカス関連のアクセシビリティ注意点
スポンサーリンク

focus() の基本的な使い方

$(function () {
  // ページ読み込み後に入力欄にフォーカス
  $('#name-input').focus();

  // ボタンクリックで別の要素にフォーカスを移動
  $('#move-btn').on('click', function () {
    $('#search-input').focus();
  });

  // フォーカスと同時にテキストを全選択
  $('#amount-input').focus().select();
});
focus() はフォーカス可能な要素にのみ有効
inputtextareaselectbuttona などは標準でフォーカス可能です。divpspan などはデフォルトでフォーカスできないため、tabindex 属性の追加が必要です。

tabindex でフォーカス可能にする

<!-- tabindex="0" で標準のタブ順序に追加 -->
<div id="custom-select" tabindex="0" role="listbox">カスタム選択肢</div>

<!-- tabindex="-1" でJSからはフォーカスできるがタブキーではスキップ -->
<div id="modal-dialog" tabindex="-1" role="dialog">モーダル内容</div>
$(function () {
  // tabindex='0' の要素: タブキーと focus() 両方でフォーカス可能
  $('#custom-select').on('keydown', function (e) {
    if (e.key === 'Enter' || e.key === ' ') {
      // Enterやスペースで選択
      $(this).toggleClass('selected');
    }
  });

  // tabindex='-1' の要素: JS から focus() でのみフォーカスできる
  // → モーダルを開くとき用(タブキーでは到達しない)
  $('#open-modal-btn').on('click', function () {
    $('#modal-dialog').show().focus();
  });
});

モーダル開閉時のフォーカス管理

アクセシビリティを考慮したモーダルでは、開いたときにモーダル内にフォーカスを移動し、閉じたときに元の要素にフォーカスを戻す必要があります。

$(function () {
  var $lastFocus; // 元のフォーカス要素を保存

  $('#open-modal-btn').on('click', function () {
    $lastFocus = $(document.activeElement); // 現在のフォーカスを保存
    $('#modal').show();
    $('#modal-first-input').focus(); // モーダル内の最初の入力欄にフォーカス
  });

  $('#close-modal-btn').on('click', function () {
    $('#modal').hide();
    $lastFocus.focus(); // 元の要素にフォーカスを戻す
  });

  // フォーカストラップ(モーダル外にフォーカスが出ないようにする)
  $('#modal').on('keydown', function (e) {
    if (e.key !== 'Tab') return;
    var $focusable = $(this).find('input, button, [tabindex="0"]').filter(':visible');
    var $first = $focusable.first();
    var $last  = $focusable.last();

    if (e.shiftKey && document.activeElement === $first[0]) {
      e.preventDefault();
      $last.focus();
    } else if (!e.shiftKey && document.activeElement === $last[0]) {
      e.preventDefault();
      $first.focus();
    }
  });
});

フォーカスイベントの使い分け

イベント バブリング 説明
focus なし 要素がフォーカスを得たとき
blur なし 要素がフォーカスを失ったとき
focusin あり 要素またはその子孫がフォーカスを得たとき(親でまとめて監視)
focusout あり 要素またはその子孫がフォーカスを失ったとき
$(function () {
  // 入力欄にフォーカスが当たったらラベルをアクティブに
  $('input').on('focus', function () {
    $(this).closest('.form-group').addClass('is-focused');
  }).on('blur', function () {
    $(this).closest('.form-group').removeClass('is-focused');
  });

  // フォーム全体のフォーカス監視(focusinはバブリングするため親で監視できる)
  $('#contact-form').on('focusin', function () {
    console.log('フォーム内のいずれかにフォーカス');
  }).on('focusout', function () {
    console.log('フォームからフォーカスが外れた');
  });
});

まとめ

jQueryでフォーカスを制御する際のポイントをまとめます。

  • 基本: $(el).focus() でプログラムからフォーカスを移動
  • tabindex=”0″: タブキーでも到達可能にする / “-1”: JSからのみフォーカス可能
  • モーダル: 開いたとき最初の要素にフォーカス → 閉じたとき元の要素に戻す
  • フォーカスイベント: focus/blur(バブリングなし)/ focusin/focusout(バブリングあり)

関連記事: フォームバリデーション完全ガイド / 画像クリックで拡大表示する完全ガイド

よくある質問(FAQ)

Qfocus()が動かないです。
A主な原因は3つです。①要素がフォーカス不可能(div等 → tabindex追加)。②要素が非表示(display:nonevisibility:hidden の要素はフォーカス不可)。③DOM読み込み前に実行している($(function(){}) 内で実行してください)。
Qバリデーションエラー後に最初のエラー欄にフォーカスしたいです。
Aエラーのある入力欄にクラスを付与し、最初の一つにフォーカスします:$(".is-error").first().focus();さらにスムーズスクロールで画面内に表示させると UX が向上します:$("html,body").animate({ scrollTop: $(".is-error").first().offset().top - 100 })
Qフォーカスのアウトラインを消したいです。
Aoutline: none でフォーカスリングを消せますが、キーボードユーザーのアクセシビリティが損なわれるため推奨されません。代わりに :focus-visible 疑似クラスを使うと、マウス操作時だけアウトラインを非表示にし、キーボード操作時は表示できます。
Qページ読み込み時に自動でフォーカスしたいです。
AHTMLの autofocus 属性が最も簡単です:<input id="search" autofocus>jQueryで行う場合は $(function() { $("#search").focus(); }); です。ただし、ページ上部にある要素以外に自動フォーカスすると、スクリーンリーダーユーザーが混乱することがあるため注意してください。
Qフォーカスが当たっている要素を取得したいです。
Adocument.activeElement で現在フォーカスされている要素を取得できます。jQueryで使う場合は $(document.activeElement) です。何にもフォーカスがない場合は document.body が返ります。