スライダー(カルーセル)の非アクティブなスライド内にリンクやボタンがある場合、タブキーで非表示スライドのリンクにフォーカスが移ってしまいます。この記事ではtabindex=”-1″・inert属性・slick.jsでの対応・アクセシビリティを損なわないフォーカス管理まで解説します。
この記事でわかること
- 非表示スライド内のリンク・ボタンをフォーカス対象から除外する
- tabindex=”-1″ で個別にフォーカスを無効化する
- inert属性でスライドごとまとめてフォーカスを無効化する
- slick.jsでの対応方法
- アクセシビリティに配慮した実装
問題: 非表示スライドにフォーカスが入ってしまう
CSSで display:none の要素はフォーカスされませんが、visibility:hidden や opacity:0、transform: 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秒以上動くコンテンツは一時停止・停止・非表示の制御ができる必要があります。自動再生スライダーには「一時停止」ボタンを必ず設けてください。ユーザーがフォーカスをスライダー内に移動したときに自動的に一時停止する実装も推奨されます。

