SST - タブに関する統一規格

SST - タブに関する統一規格
基準

62

11 分。

定義

SST規格は、タブのセマンティクス、アクセシビリティ、および動作ロジックに関する要件を規定しています。

構造と動作

コンテナーとスクロール

  • タブは一列に並べる。SST-Aの規約では、狭い画面でも次の行へ折り返さず、ドロップダウンにも置き換えない。
  • タブ列専用のコンテナーにoverflow-x: autoを設定する。横スクロールするのはタブ列だけで、ページ全体ではない。パネルの内容は画面幅に合わせてリフローさせる。
  • タブを二段目に配置しない。タブの幅を保ち、項目がコンテナーを超える場合は横スクロールで表示する。
  • 可能であれば、コンテナーの端に次のタブの一部が見えるようにする。表示する幅の目安は10–20px。リストが続くことを視覚的に示せるため、装飾的な矢印アイコンは必須ではない。選択中タブのラベルやフォーカスインジケーターは切り取らない。この視覚的な手掛かりはキーボード操作の代わりにはならない。
  • モバイルでは、次のタブの一部など別の手掛かりでスクロール可能と分かる場合、システムのスクロールバーを非表示にしてもよい。非表示にしても、キーボードでスクロールできる状態を保つ。
  • -webkit-overflow-scrolling: touchをスムーズなスクロールの基本要件とはしない。現在のiOSおよびiPadOSでは、このプロパティがなくてもoverflow領域のスクロールが高速化される。iPhoneでは、指定によってスタッキングコンテキストが作られる場合もある。明示的にサポートする旧バージョンがあり、実機検証で必要と判断された場合に限って追加する。

選択中タブとセンタリング

  • 選択中タブには、アクセントラインや背景色の変更など、明確な視覚状態を設ける。色だけで状態を区別しない。

  • タブを選択したとき、キーボードフォーカスが移動したとき、または直接リンクからページを開いたとき、選択中タブが表示範囲に入り、可能な範囲で中央に近づくようにスクロールする。

  • センタリングはスクロール可能範囲内で行う。コンテナーの端にある最初と最後のタブは、常に正確な中央へ配置できるとは限らない。

  • LTRレイアウトでは、スクロール内容の先頭を基準に目標値を計算できる。

    targetScrollLeft = clamp(tabStart + tabWidth / 2 - viewportWidth / 2, 0, scrollWidth - viewportWidth)

    tabStartはスクロール領域の先頭から見たタブの位置を表す。RTLレイアウトでは書字方向とブラウザーごとの横スクロールの違いを考慮し、可能な場合は論理方向を扱うスクロールAPIを使用する。

識別とURL

タブとパネルの関連付け

  • コンテナーにrole="tablist"を設定し、表示される見出しへのaria-labelledby、またはaria-labelでアクセシブルな名前を付ける。
  • 各タブにrole="tab"、一意で安定したid、関連パネルを指すaria-controls="panel-id"を設定する。
  • 各パネルにrole="tabpanel"、一意なid、操作元のタブを参照するaria-labelledby="tab-id"を設定する。
  • 選択中タブはaria-selected="true"、それ以外のタブはaria-selected="false"にする。未選択のパネルは、たとえばhidden属性で非表示にする。
  • roving tabindexを実装する。選択中タブはtabindex="0"、それ以外はtabindex="-1"にする。フォーカス可能な内容がないパネルにはtabindex="0"を設定し、キーボード操作で到達できるようにしてもよい。

ハッシュとディープリンク

  • 各タブに一意で安定した識別子を付け、#tab-idのようにURLフラグメントで安全に使用できるようにする。URLで安全な識別子を使うか、ハッシュの読み取り時に一貫してエンコード・デコードする。
  • ページの初期読み込み時にハッシュとタブを照合する。一致するタブがあれば、そのタブとパネルを有効にしてからタブ列をスクロールする。不明なハッシュの場合は既定のタブを表示する。
  • タブ選択時に、選択した履歴管理方法に従ってURLを更新する。history.replaceStateは現在の履歴エントリーを更新し、タブを切り替えるたびに「戻る」の履歴を追加しない。アプリケーションは同じイベント処理内でタブ状態を更新し、hashchangeイベントに依存しない。
  • 「戻る」「進む」で以前のタブ選択を復元する場合は、history.pushStateを使い、popstateイベントでタブ状態を同期する。
  • ハッシュ更新時にパスやクエリーパラメーターを削除しない。不明または不正なハッシュの場合も、既定のタブを使って操作できる状態を保つ。

アクセシビリティとキーボード操作

  • tablist、tab、tabpanelは、同一ページ内でパネルを切り替えるタブにのみ使用する。別ページへの移動には、見た目がタブでもリンクを使用する。
  • Tabキーでタブ列に入ると、選択中タブにフォーカスが移る。次のTabキーでタブリストを抜け、パネル内の内容または次のページ要素に移動する。
  • 横並びのリストでは←と→でタブ間のフォーカスを移動し、端に達したら反対側の端へ移る。RTLでは、キーの方向を視覚的な順序と読み方向に合わせる。
  • HomeとEndで先頭または末尾のタブにフォーカスを移動してもよい。手動アクティベーションでは、フォーカス中のタブをEnterまたはSpaceで選択する。自動アクティベーションでは、フォーカスに合わせて選択状態を切り替える。
  • 関連パネルが目立った遅延なく表示される場合は、自動アクティベーションを使用する。パネルの読み込みが遅い場合は手動アクティベーションを使い、フォーカス移動による遅延を避ける。
  • フォーカス移動時に選択中タブを表示範囲へスクロールする。フォーカスインジケーターをコンテナーで切り取らない。

テスト

  • モバイル幅でもタブが一列に並び、スワイプでスクロールでき、横スクロールがページ全体に広がらない。
  • 次のタブの一部、または別のインジケーターでスクロール可能と明確に分かる。スクロールバーを隠しても有用なフィードバックが失われない。
  • 選択中タブが視覚的およびプログラム上で示され、aria-selected、aria-controlsとaria-labelledbyの関連付け、パネルの表示状態が同期している。
  • タブリストにアクセシブルな名前があり、各タブのラベルが明確であることをスクリーンリーダーで確認する。
  • キーボード操作が選択したアクティベーション方式に従い、リストの両端で動作し、RTLの方向も考慮されている。
  • クリック、キーボード操作、ハッシュ付きURLからの読み込み後に選択中タブが表示される。先頭・末尾でセンタリングが制限されることも確認する。
  • 正しいハッシュと不明なハッシュを含む直接リンクを、初期読み込みとページ再読み込みの両方で確認する。
  • replaceStateを使用する場合、タブの切り替えでアドレスは更新されるが、タブごとの履歴エントリーは追加されない。pushStateを使う場合、「戻る」「進む」でURL、選択中タブ、パネルが同期する。
  • タッチとキーボードでのスクロールを維持したままスクロールバーを非表示にする。iOS、Androidを含む対象ブラウザーで表示と動作を確認する。
  • センタリングやスムーズスクロールがprefers-reduced-motion: reduceを有効にしたユーザーの妨げにならない。

例

パネルとARIA属性を関連付けたタブ列:

<div class="tabs__viewport">
  <div class="tabs__list" role="tablist" aria-label="ドキュメントのセクション">
    <button
      id="tab-overview"
      type="button"
      role="tab"
      aria-controls="panel-overview"
      aria-selected="true"
      tabindex="0"
    >
      概要
    </button>
    <button
      id="tab-details"
      type="button"
      role="tab"
      aria-controls="panel-details"
      aria-selected="false"
      tabindex="-1"
    >
      詳細
    </button>
  </div>
</div>

<section
  id="panel-overview"
  role="tabpanel"
  aria-labelledby="tab-overview"
  tabindex="0"
>
  「概要」セクションの内容。
</section>

<section
  id="panel-details"
  role="tabpanel"
  aria-labelledby="tab-details"
  tabindex="0"
  hidden
>
  「詳細」セクションの内容。
</section>

一列のスクロール可能なタブ列を作るCSS:

.tabs__viewport {
  overflow-x: auto;
  padding: 2px;
  scroll-behavior: smooth;
}

.tabs__list {
  display: flex;
  flex-wrap: nowrap;
  width: max-content;
  min-width: 100%;
}

.tabs__list [role="tab"] {
  flex: 0 0 auto;
  white-space: nowrap;
}

.tabs__list [role="tab"][aria-selected="true"] {
  border-block-end: 2px solid currentColor;
}

.tabs__list [role="tab"]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

@media (max-width: 767px) {
  .tabs__viewport {
    scrollbar-width: none;
  }

  .tabs__viewport::-webkit-scrollbar {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tabs__viewport {
    scroll-behavior: auto;
  }
}

モバイルでは、次のタブの一部を見せることで、非表示にしたスクロールバーの代わりにスクロール可能であることを示す。見える幅はコンテナーとラベルに応じて調整し、選択中タブとフォーカスインジケーターは完全に表示する。

メディアクエリーの767pxは例であり、SST-Aの固定要件ではない。プロジェクトのレスポンシブ設計で使用するブレークポイントに置き換える。

タブのセンタリングとURL同期:

const centerTab = (tab) => {
  tab.scrollIntoView({
    block: 'nearest',
    inline: 'center'
  })
}

const findTabFromUrl = (tabs) => {
  const tabId = window.location.hash.slice(1)

  return tabs.find((tab) => tab.id === tabId) || null
}

const updateTabUrl = (tab) => {
  window.history.replaceState(null, '', '#' + tab.id)
}

初期化時にfindTabFromUrlで見つかったタブと対応するパネルを有効にし、そのタブをcenterTabに渡す。ユーザーがタブを選択したときは、まずaria-selected、roving tabindex、パネルの表示状態を更新し、続けてcenterTabとupdateTabUrlを呼び出す。この例は状態、URL、スクロールの同期を示すもの。キーボード用ハンドラーは上記のルールに従って実装する。

類似カテゴリ:

関連記事

  • Reactコンポーネントの構造

    各Reactコンポーネントがどのような外観であるべきか、私の考え

    421

    13 分。

  • SSF-U - フルスクリーン表示の統一規格

    SSF-U規格は、フルスクリーン表示のセマンティクス、アクセシビリティ、および動作ロジックに関する要件を規定しています

    248

    3 分。

  • SSA - アコーディオンの統一標準

    SSA規格は、アコーディオンのセマンティクス、アクセシビリティ、および動作ロジックに関する要件を定めています

    258

    4 分。

  • ウェブサイトにおける悪い慣行

    ウェブデザインにおける致命的なミスの分析。スライダー、自動再生、重いページがコンバージョン率やGoogleでの検索順位を低下させる理由

    232

    2 分。

  • SSP - ページネーションの統一規格

    SSP規格は、ページネーションのセマンティクス、アクセシビリティ、および動作ロジックに関する要件を規定しています

    240

    3 分。

  • SSPS - プロジェクト構造の統一基準

    SSPS標準は、プロジェクト内のファイルおよびフォルダの構造と命名に関する要件を規定しています

    345

    3 分。

  • すべての記事

ご連絡ください