mcpField
A
a11y

a11y

github.com/paragonhqデザイン・UI045 回インストール5 週間前に更新
リポジトリ

a11y について

ウェブインターフェースを設計・実装する開発者向けのアクセシビリティ実践スキルです。セマンティック HTML、キーボード操作、フォーカス、フォーム、コントラスト、モーション、ページ構造を扱い、短い確認手順も含みます。

主な機能

  1. 01セマンティック HTML の優先
  2. 02アクセシブルな名前とキーボード操作
  3. 03フォーカス、ARIA、ダイアログの指針
  4. 04フォーム、コントラスト、モーションへの対応
  5. 05構造、ズーム、時間制限への配慮
  6. 065 分で行うアクセシビリティ確認

活用シーン

  1. 01キーボードで操作できる画面を設計する
  2. 02フォームのラベルとエラー表示を確認する
  3. 03ダイアログのフォーカス管理を改善する
  4. 04ズーム、コントラスト、モーション軽減を確認する

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/paragonhq/stealth-skills --skill a11y

インストール後、Claude Code で/a11yを入力して読み込まれたか確認します。

詳細

a11y

アクセシブルなインターフェースは、優れたインターフェースとは別物ではありません。ここにあるルールのほとんどは、マウスを使い、視力に問題のない人にとってもインターフェースをより使いやすくします。コンプライアンスではなく、技術として捉えましょう。

まずはHTMLから

要素そのものが振る舞いを担います。適切な要素を使いましょう。

目的使うもの使わないもの
操作を実行するもの<button type="button"><div onClick>
ページ遷移するもの<a href>router.pushを呼び出す<button>
リスト<li>を含む<ul>/<ol>div
フォーム<button type="submit">を含む<form>フォーム外のボタンに設定したonClick
チェックボックス、ラジオボタン、スイッチ<input type="checkbox">、またはボタンに設定したrole="switch"カスタムのdiv
見出しのあるセクション<section aria-labelledby>太字の段落を含むdiv
強調<strong>、<em><b>、<i>、またはfont-weightを設定したspan
ダイアログ<dialog>、またはrole="dialog"を持つプリミティブ固定表示のdiv

ネイティブ要素なら、キーボード操作、フォーカス、ロール、名前が最初から備わっています。これらをカスタム要素で置き換える場合は、4つすべてを自分で補う必要があります。

名前

すべてのコントロールにはアクセシブルな名前が必要です。優先順位は次のとおりです。

  1. 要素内にある表示テキスト(<button>変更を保存</button>)。
  2. 表示されている<label for>(入力欄)。
  3. 表示テキストを参照するaria-labelledby。
  4. アイコンのみのコントロールに限りaria-labelを使います。アイコンが何かではなく、コントロールが何をするかを表します(「リンクをコピー」であり、「クリップボードのアイコン」ではありません)。

画像には、画像が伝える内容を示すaltを設定します。装飾目的の場合はalt=""にします。ラベル付きコントロール内のアイコンにはaria-hiddenを設定します。

名前は、その文脈内で一意にします。リストに「編集」ボタンが5つある場合は、表示上またはaria-labelで「第3四半期のレポートを編集」とします。

キーボード

  • 操作可能な要素はすべて、視覚的な順序でTabキーから到達できるようにします。tabindexは0または-1とし、正の値は使いません。
  • カスタムウィジェットは、そのロールに対応するARIAパターンに従います。メニュー、タブ、リストボックス、ラジオグループ内では矢印キーを使い、Tabキーでウィジェットの外に移動します。
  • Escapeキーで閉じるのは、最前面のレイヤーだけです。
  • ダイアログを開いたらフォーカスを中に移動し、開いている間はフォーカスを閉じ込めます。閉じたら、起動元にフォーカスを戻します。
  • モーダルの背後にあるコンテンツにはinertを設定します。
  • スキップリンクは、最初にフォーカス可能な要素とし、フォーカス時に表示します。
  • テキストフィールドにフォーカスがある間は単一キーのショートカットを発動させません。修飾キーを使うショートカットは、ブラウザーのショートカットと競合させません。
  • 複合ウィジェットではロービングtabindexまたはaria-activedescendantを使い、ウィジェットごとにTabキーで移動できる箇所を1つにします。

フォーカスの視認性

:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }
  • あらゆる背景色で見えるようにします。最も暗い色と最も明るい色の両方でテストします。
  • 要素の角丸に合わせます。
  • 代わりとなる表示が要素とその背景の両方に対して3:1以上のコントラストを持たない限り、outline: noneは使いません。
  • リンクとして機能する行やカードでは、テキストだけでなく行全体にフォーカスを表示します。

ARIAは必要最小限に

ARIAの第一のルールは、HTMLで実現できる場合はARIAを使わないことです。そのうえで、次のようにします。

  • 展開する要素のトリガーにはaria-expandedを設定し、対象要素を指すaria-controlsを設定します。
  • 現在のナビゲーションリンクにはaria-current="page"を設定します。ページ内ナビゲーションにはaria-current="location"を設定します。
  • トグルボタンにはaria-pressed、スイッチとチェックボックスにはaria-checked、タブとオプションにはaria-selectedを設定します。
  • 読み込み中の領域にはaria-busyを設定します。無効なコントロールにフォーカスを維持する必要がある場合はaria-disabledを設定します。
  • 入力欄からエラーとヒントを参照するにはaria-describedbyを使います。
  • トーストやステータスを通知する領域にはaria-live="polite"を設定します。assertiveを使うのは、処理を妨げるエラーに限ります。
  • 装飾アイコン、視覚的な重複(アニメーションのために単語を複数のspanに分割する場合は、親要素にaria-labelを設定します)、バックドロップにはaria-hidden="true"を設定します。
  • ボタンで実現できる場合、divにrole="button"を設定してはいけません。ロールのないdivにaria-labelを設定してはいけません。

フォーム

  • すべてのフィールドに見えるラベルを付けます。プレースホルダーはヒントです。
  • 必須フィールドには印を付け、その印の意味を一度説明します。
  • エラーは、フィールドからフォーカスが外れた後、または送信後に表示し、フィールドの下に配置して aria-describedby で関連付けます。送信時には、最初の無効なフィールドにフォーカスを移します。
  • エラーテキストでは、何が問題で、どうすれば解決できるかを言葉で伝えます。色とアイコンも添えますが、それらで代用してはいけません。
  • ラジオボタンやチェックボックスのグループは、<legend> を含む <fieldset> に入れます。
  • ブラウザーや支援技術が入力を補完できるように autocomplete を設定します。
  • どのフィールドからでも Enter キーで送信できるようにします。

色とコントラスト

  • どちらのテーマでも、テキストは 4.5:1、大きなテキストと UI の境界は 3:1 を確保します。
  • 色だけを唯一の手がかりにしてはいけません。ステータスにはアイコンか言葉を添え、本文中のリンクには下線を付け、グラフにはパターンかラベルを付けます。
  • プレースホルダーと無効状態のテキストは、読み取る必要がない場合に限り、コントラスト比を 4.5:1 未満にできます。
  • フォーカスリングと選択色が、すべての背景面に対して適切か確認します。
  • prefers-contrast: more の場合は、境界線の色を --fg-2 にし、半透明をなくします。
  • forced-colors: active(Windows のハイコントラストモード)の場合は、背景色に依存していたコントロールに境界線を付け、フォーカスには outline を使い、意味を伝えるための background-image は使いません。

モーション

  • prefers-reduced-motion: reduce の場合は、トランジションとアニメーションをほぼゼロにし、スムーズスクロールと視差効果を無効にして、自動再生動画を一時停止します。ただし、何も非表示にしてはいけません。アニメーションで表示される要素は、そのまま表示しておきます。
  • 1 秒あたり 3 回を超えて点滅させてはいけません。
  • 5 秒を超える自動再生の動きには、一時停止コントロールを付けます。

構造

  • ページごとに h1 を 1 つだけ使い、見出しのレベルを飛ばさず順番に並べます。スクリーンリーダーの利用者が移動したい各領域に見出しを付けます。
  • ランドマークには、main、header、footer、nav(複数ある場合はラベルを付ける)、aside、search を使います。
  • リストにはリストを使います。行ベースの UI には、aria-label を指定した <ul> を使います。
  • 表には <th scope> を含む <table> を使うか、適切なロールを持つグリッドを使います。div は使いません。
  • ドキュメントと、別の言語で書かれた箇所には lang を指定します。
  • DOM の読み上げ順序を視覚的な順序に合わせます。CSS の order と flex-direction: row-reverse はこれを崩します。

サイズとズーム

  • WCAG に従い、ターゲットの最小サイズを 24px とします。タッチ操作では実際には 44px を確保します。
  • ブラウザーのズームを 200% にした場合も、幅 320px の場合も、横スクロールやコンテンツの欠落なくページを使えるようにします。
  • テキストの間隔(line-height 1.5、letter-spacing 0.12em、word-spacing 0.16em)を広げても、テキストがクリップされないようにします。
  • ピンチズームを無効にしてはいけません。

時間制限

  • トーストは少なくとも 5 秒間表示し、アクションがある場合はさらに長く表示します。ホバー中とフォーカス中は一時停止します。
  • セッションがタイムアウトする場合は、延長できる時間を残して警告します。
  • 利用に時間制限のある応答を求めてはいけません。

5 分間のテスト

  1. マウスを外します。画面内を Tab キーで移動します。現在の位置が見えますか?すべての操作ができますか?
  2. VoiceOver(⌘F5)または NVDA を起動します。見出しで移動します(VO+⌘+H)。見出しはページの内容を説明していますか?コントロールまで Tab キーで移動し、それぞれの役割、名前、状態が読み上げられますか?
  3. ダイアログを開きます。フォーカスはダイアログ内にありますか?Escape キーで閉じて、フォーカスを元の場所に戻せますか?
  4. ズームを 200% にします。引き続き使えますか?
  5. モーションの低減を有効にします。何か表示されなくなりますか?
  6. axe を実行します。「serious」と「critical」の問題をすべて修正します。「moderate」の問題も確認します。多くは実際の問題です。

アクセシブルでない UI の兆候

兆候修正方法
div onClickbutton
outline: none:focus-visible のリング
名前のないアイコンボタンaria-label
ラベルとして使うプレースホルダー見えるラベル
赤いテキストだけのエラーアイコン + テキスト + aria-describedby
フォーカストラップのないモーダルダイアログプリミティブ、背面に inert
カスタムセレクトネイティブの <select> またはリストボックスプリミティブ
ホバー時にしか表示されない操作の手がかり常に表示するか、フォーカス時にも表示する
動きを減らすとコンテンツが隠れるコンテンツは表示し、動きはなくす
色だけで示すステータスアイコンか言葉

カタログから

  • Sara Soueidan — アクセシビリティと SVG を、実際に開発している人が解説しています。
  • ARIA Authoring Practices — 各パターンのキーボード操作とロールに関する仕様です。
  • Inclusive Components — 最初からアクセシブルに構築されたコンポーネントです。
  • axe、Polypane — すでに開いているブラウザーでテストできます。
  • Nielsen Norman Group — このリストの内容とほぼ全面的に重なるユーザビリティ調査です。
  • 詳細は stealth.pm/tools をご覧ください。

コメント