複数のコンテンツアイテム(画像・カード・テキスト)を横スクロールまたはスライド形式で切り替えるUIコンポーネント。前後ナビゲーションボタン・ドットインジケーター・自動再生・スワイプ操作を組み合わせた複合UIで、ランディングページのヒーロー画像・ECの商品ギャラリー・レビュー一覧・メディアのフィーチャー記事など幅広い場面で使われる。
この記事を読むと、Carousel vs 静的一覧の使い分け・自動再生の弊害と制御・スライドアイテムのARIA実装(role="group" + aria-roledescription)・prefers-reduced-motion 対応・インジケーターの設計が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
複数のアイテムを横方向にスライドして切り替えるUIコンポーネント。1枚表示・複数枚部分表示・ループ再生など多様な実装がある。
Carousel vs 静的一覧:
| Carousel | 静的一覧 | |
|---|---|---|
| 視認性 | 1度に1〜数枚のみ | 全件一覧で比較可能 |
| 発見性 | 低い(隠れたアイテムを見落とす) | 高い |
| スペース効率 | 高い(省スペース) | 低い(縦に伸びる) |
| 向いている用途 | ヒーロー画像・ギャラリー・レビュー | 商品比較・記事一覧・フィルター結果 |
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- ヒーロービジュアルの切り替え:LPのメインビジュアル・キャンペーンバナー
- 画像ギャラリー:商品詳細の複数画像・ポートフォリオ
- テスティモニアル(レビュー):ユーザーの声を1つずつ強調して表示
- スペースが限られている場面:モバイルでカードを横スクロールで表示
3.2 When NOT to use
- 比較が必要な商品一覧:ユーザーが全商品を比較できないCarouselは不向き
- 重要な情報のすべてをCarouselに入れる:隠れたスライドは見落とされる確率が高い
- ナビゲーション要素:メニューやタブの代替にCarouselを使わない
4. 設計判断の核(Decision Principles)
Carouselの核は「自動再生を使う場合の一時停止コントロール」——WCAG 2.2の達成基準2.2.2では、5秒以上動くコンテンツには一時停止・停止・非表示の手段を提供することを要求している。自動再生は発見性を下げ、前庭障害のユーザーに悪影響を与える。
判断の優先順位:① 自動再生の是非 → ② role="group" + aria-roledescription → ③ ドットインジケーターのARIA → ④ スワイプ対応
- 自動再生はデフォルトOFF、または
prefers-reduced-motionで無効化する:@media (prefers-reduced-motion: reduce)で自動再生を止める。ユーザーが自動再生を有効にした場合も、一時停止ボタン(またはaria-label="自動再生を停止"ボタン)を提供する - 各スライドに
role="group"+aria-roledescription="スライド"+aria-label="N / 全M枚":スクリーンリーダーが「スライド 1 / 5:タイトル」と読み上げられるようにする。カルーセル全体を囲む要素にはrole="region"+aria-roledescription="カルーセル"+aria-labelを設定する - ドットインジケーターは
role="tab"+aria-selected:各ドットにスライド番号をaria-label="スライド N"で示す。現在のスライドにaria-selected="true"を設定する - スライド切り替え後は
aria-live="polite"でカウンターを読み上げる:「2 / 5」のようなカウンターにaria-live="polite" aria-atomic="true"を設定し、切り替えを音声で通知する
5. 状態設計(States)
| 状態 | 表示 | aria |
|---|---|---|
| アクティブスライド | フォーカス・表示 | aria-selected="true" |
| 非アクティブスライド | 非表示または部分表示 | aria-selected="false" |
| 自動再生中 | インジケーターがアニメーション | 一時停止ボタン表示 |
| 一時停止中 | 静止 | 再生ボタン表示 |
| ループ先頭 | 最後のスライドから最初に戻る | — |
6. バリエーション設計(Variants)
| バリアント | 説明 | 使用例 |
|---|---|---|
| Hero Carousel | 1枚フルワイド表示 | LPのメインビジュアル |
| Card Carousel | 複数カードの部分表示付き | 関連記事・商品一覧 |
| Testimonial Carousel | テキスト中心の1枚表示 | レビュー・お客様の声 |
| Thumbnail Carousel | サムネイル付き選択UI | 商品画像ギャラリー |
| Infinite Scroll Carousel | 横方向の無限スクロール | SNSのフィード・タイムライン |
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- 自動再生が止まらない:5秒ごとにスライドが切り替わり続け、ユーザーに読む時間を与えない
- ARIAが実装されていない:
<div>の羅列で実装されており、スクリーンリーダーがスライドを識別できない - キーボードでナビゲーションできない:矢印ボタンが
<div onClick>で実装されており、Tabキーでフォーカスできない
7.1 Bad(典型3つ)
setIntervalで自動再生し、停止する手段を提供していない- スライドを
<div>の羅列で実装し、role="group"もaria-labelもない - 前後ボタンが
<div onClick>でaria-labelがなく「左矢印」「右矢印」と読み上げられる
7.2 Good(対になる3つ)
useEffectで自動再生を制御し、autoPlaystateのtoggleボタンとprefers-reduced-motionで自動再生を無効化する<div role="region" aria-roledescription="カルーセル">でラップし、各スライドにrole="group" aria-roledescription="スライド" aria-label="1 / 5:タイトル"を設定する<button aria-label="前のスライド">+<button aria-label="次のスライド">で実装する
7.3 How to fix(手順)
- スライドコンテナに
role="region" aria-roledescription="カルーセル" aria-labelを追加 - 各スライドに
role="group" aria-roledescription="スライド" aria-label="N / 全M枚"を追加 - ナビゲーションボタンを
<button aria-label="前のスライド/次のスライド">に変更 prefers-reduced-motionで自動再生を無効化し、一時停止ボタンを追加
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Screen Reader
<section
role="region"
aria-roledescription="カルーセル"
aria-label="おすすめ記事"
>
<div
role="group"
aria-roledescription="スライド"
aria-label="1 / 5:ビジュアルデザインの基礎"
>
<!-- スライドコンテンツ -->
</div>
<button aria-label="前のスライド">‹</button>
<button aria-label="次のスライド">›</button>
<div role="tablist" aria-label="スライドを選択">
<button role="tab" aria-selected="true" aria-label="スライド 1" />
<button role="tab" aria-selected="false" aria-label="スライド 2" />
</div>
<p aria-live="polite" aria-atomic="true">1 / 5</p>
</section>
10. 実装メモ(Implementation Notes)
embla-carousel-reactはキーボードナビゲーション・スワイプ・ARIA対応が充実した軽量ライブラリ。shadcn/ui のCarouselコンポーネントも Embla ベース- 自動再生の
prefers-reduced-motion対応:const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;で判定し、trueの場合は自動再生を初期化しない - タッチスワイプの実装:
onTouchStartで開始X座標を記録し、onTouchEndでdiff > 50px なら前後に切り替える。またはPointer Events APIを使う - 複数枚部分表示のLayout:
display: flex+overflow: hidden+ スライドにmin-width: calc(100% / N)のアプローチが基本
11. 関連リンク
- 関連するUIデザイン原則: 視覚的階層 (Visual Hierarchy), フィードバック (Feedback)
- 用語集(定義): アクセシビリティ
- 関連するUIコンポーネント(横): Image / Media(画像・メディア), Card(カード), Scroll Area(スクロールエリア), Pagination(ページネーション)
12. まとめ
Carouselの設計で最重要なのは「自動再生の一時停止コントロール」と「role="group" + aria-roledescription のARIA実装」です。CarouselはビジュアルインパクトのあるUIですが、アクセシビリティ実装が最も疎かになりやすいコンポーネントの1つです。自動再生はデフォルトOFFまたは prefers-reduced-motion で無効化し、必ず停止手段を提供してください。重要な情報をCarouselに入れる場合は、隠れたスライドが見落とされることを前提に、代替の静的一覧も検討してください。