【jQuery】スライダーの非表示スライドにタブキーでフォーカスさせない方法|tabindex・inert・slick・アクセシビリティまで

【jQuery/slick】スライドにタブでフォーカスさせない設定方法 jQuery

スライダー(カルーセル)の非アクティブなスライド内にリンクやボタンがある場合、タブキーで非表示スライドのリンクにフォーカスが移ってしまいます。この記事ではtabindex=”-1″・inert属性・slick.jsでの対応・アクセシビリティを損なわないフォーカス管理まで解説します。

この記事でわかること

  • 非表示スライド内のリンク・ボタンをフォーカス対象から除外する
  • tabindex=”-1″ で個別にフォーカスを無効化する
  • inert属性でスライドごとまとめてフォーカスを無効化する
  • slick.jsでの対応方法
  • アクセシビリティに配慮した実装
スポンサーリンク

問題: 非表示スライドにフォーカスが入ってしまう

CSSで display:none の要素はフォーカスされませんが、visibility:hiddenopacity:0transform: translateX(-100%) などでスライド外に移動している場合は、見た目は隠れていてもフォーカス可能な状態のままです。

ユーザーがタブキーで操作すると、見えないスライドのリンクにフォーカスが移って混乱します。

方法1: tabindex=”-1″ で個別にフォーカスを無効化

$(function () {
  var FOCUSABLE = 'a, button, input, select, textarea, [tabindex]';

  function updateFocusable() {
    // 全スライドのフォーカス可能要素を -1 に
    $('.slide').find(FOCUSABLE).attr('tabindex', '-1');

    // アクティブなスライドのみ0に戻す
    $('.slide.is-active').find(FOCUSABLE).attr('tabindex', '0');
  }

  updateFocusable(); // 初期化

  // スライド切り替え時に更新
  $('.prev-btn, .next-btn').on('click', function () {
    // スライドを切り替える処理...
    updateFocusable();
  });
});
tabindex=”0″ は元の tabindex を上書きする
もとから tabindex 属性を持たない要素に tabindex="0" を設定すると、タブ順序に追加されます。tabindex="-1" にするとタブキーではアクセスできなくなりますが、JavaScriptからの focus() は引き続き使えます。

方法2: inert属性でスライドごとまとめてフォーカス無効化(推奨)

HTML5の inert 属性を使うと、要素内の全インタラクションを一括で無効化できます。フォーカス・クリック・スクリーンリーダーの読み上げも無効になります。

$(function () {
  function updateSlides(activeIndex) {
    $('.slide').each(function (i) {
      if (i === activeIndex) {
        // アクティブスライド: inert を削除
        this.removeAttribute('inert');
        $(this).attr('aria-hidden', 'false');
      } else {
        // 非アクティブスライド: inert を設定
        this.setAttribute('inert', '');
        $(this).attr('aria-hidden', 'true');
      }
    });
  }

  var currentSlide = 0;
  updateSlides(currentSlide);
});
inert属性はアクセシビリティにも優れた解決策
inert 属性はフォーカス・クリック・スクリーンリーダーの全てを無効化します。aria-hidden="true" と組み合わせることで、スクリーンリーダーが非アクティブスライドを読み上げなくなります。全モダンブラウザで対応済みです(IE非対応)。

slick.js での対応方法

slick.js は accessibility: true(デフォルト)を設定すると、非アクティブスライドに aria-hidden="true" を自動で付与します。しかしフォーカス管理は完全ではない場合があるため、追加の対応が必要なことがあります。

$(function () {
  $('#slider').slick({
    accessibility: true, // aria属性を自動管理(デフォルトtrue)
    // ...その他オプション
  });

  // slickのafterChange後にfocusableを更新
  $('#slider').on('afterChange', function (event, slick, currentSlide) {
    var FOCUSABLE = 'a, button, input, [tabindex]';

    // 全スライドのフォーカスを無効化
    $(this).find('.slick-slide').find(FOCUSABLE).attr('tabindex', '-1');

    // 表示中のスライドのみ有効化
    $(this).find('.slick-slide:not([aria-hidden=true])').find(FOCUSABLE).attr('tabindex', '0');
  }).trigger('afterChange', [null, null, 0]); // 初回実行
});

各方法の比較

方法 フォーカス無効 クリック無効 スクリーンリーダー 対応ブラウザ
tabindex="-1" タブキーのみ なし 読む 全て
inert属性 全フォーカス 無効 読まない モダン(IE非対応)
display:none 全フォーカス 無効 読まない 全て

まとめ

スライダーのフォーカス管理のポイントをまとめます。

  • 基本: スライド切り替え時に tabindex="-1"/-"0" を更新
  • 推奨: inert 属性 + aria-hidden="true" でまとめて無効化
  • slick.js: afterChange後にtabindexを更新
  • フォーカス管理はアクセシビリティの重要な要素

関連記事: 要素にフォーカスを当てる完全ガイド / 各スライドの高さを揃える方法完全ガイド

よくある質問(FAQ)

Qtabindex=”-1″にしたのにタブでフォーカスされます。
Aスライド内に後から動的に追加されたリンクや、CSSで tabindex が上書きされていないか確認してください。また、スライド切り替えのコールバックで毎回 tabindex を更新しているか確認してください。ブラウザの開発者ツールで問題のリンクの tabindex 属性を確認するのが確実です。
Qinert属性はWordPressでも使えますか?
Aはい。inert はHTML属性なので、WordPressの制約はありません。jQuery経由で el.setAttribute("inert", "") または el.removeAttribute("inert") で操作できます。IE対応が必要な場合は wicg-inert ポリフィルを使ってください。
QSwiper.jsでも同じ対応が必要ですか?
ASwiper.js v8以降は a11y: true(デフォルト)でaria属性を自動管理し、focusableElements オプションでフォーカス対象を制御できます。Swiper自体のアクセシビリティ対応はslick.jsより進んでいますが、複雑なスライド内容では追加の tabindex 制御が必要な場合があります。
Qスクリーンリーダーユーザーのためにどんな対応が必要ですか?
A①非アクティブスライドに aria-hidden="true" を設定(スクリーンリーダーがスキップ)。②スライダーに role="region"aria-label="スライダー" を設定。③スライド切り替えボタンに分かりやすいラベル(aria-label="次のスライド")を設定。これらを組み合わせることでスクリーンリーダーユーザーにも理解しやすいスライダーになります。
Q自動再生スライダーのアクセシビリティはどうすればよいですか?
AWCAG 2.1の基準では、5秒以上動くコンテンツは一時停止・停止・非表示の制御ができる必要があります。自動再生スライダーには「一時停止」ボタンを必ず設けてください。ユーザーがフォーカスをスライダー内に移動したときに自動的に一時停止する実装も推奨されます。