swiper/reactで実装したカルーセルをTAB操作した時、画面に描画されていないスライドにフォーカスが当たってしまう
最終更新日: 2024-07-27記事投稿日: 2024-07-27
概要
カルーセルのスライドは多くの場合、リンクになっているためTABキーでフォーカスが当てられるようになっています。
しかし、何も対策しないとTABキー操作をした時に画面に描画されていないスライドにもフォーカスが当たってしまいます。これはWCAG2.0の達成基準2.4.3「フォーカスの順序」や達成基準2.4.7「フォーカスの可視化」の基準が満たせなくなるため好ましくない状態です。
修正方法
IntersectionObserverを利用して画面に描画されているかを検知し、tabindex
とaria-hidden
を制御することで修正対応しました。
tabindex
は-1
を指定すればfocusしないようになり、0
を付与すればページのソース内の順序でfocusされるようになります。
参考コードは以下になります。
import React, { useRef, useEffect } from 'react';
export const SlideItem = ({ index }) => {
const ref = useRef(null)
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
ref.current?.setAttribute('aria-hidden', entry.isIntersecting ? false : true)
ref.current?.setAttribute('tabindex', entry.isIntersecting ? 0 : -1)
});
observer.observe(ref.current);
return () => observer.disconnect();
}, [])
return (
<a href="/" ref={ref}>
<img src={`https://placehold.jp/150x150.png?text=${index}`} alt={index} />
</a>
)
}
上記コンポーネントを以下のようにswiperから提供されているコンポーネントでラップしてあげるとフォーカスの制御がうまくいきます。
import React, { useRef, useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/pagination';
import 'swiper/css/navigation';
import './styles.css';
import { Pagination, Navigation } from 'swiper/modules';
import { SlideItem } from './SlideItem';
export default function App() {
return (
<>
<Swiper
slidesPerView={3}
navigation={true}
pagination={true}
loop={true}
modules={[Pagination, Navigation]}
className="mySwiper"
>
{[1,2,3,4,5,6,7,8,9].map(index => (
<SwiperSlide key={index}>
<SlideItem index={index}/>
</SwiperSlide>
))}
</Swiper>
</>
);
}