ベストプラクティス

Angularにおけるアクセシビリティ

ウェブは、視覚または運動障害のある人々を含む、さまざまな人々によって利用されています。 これらのグループがウェブベースのソフトウェアアプリケーションとより簡単にやり取りできるようにする、さまざまな支援技術が利用可能です。 また、アプリケーションをよりアクセシブルに設計することで、一般的にすべてのユーザーのユーザー体験が向上します。

アクセシブルなアプリケーションの設計に関する問題とテクニックの包括的な紹介については、Googleのweb.dev アクセシビリティを学ぶコースを参照してください。

このページでは、支援技術に依存する人々を含むすべてのユーザーにとって適切に機能するAngularアプリケーションを設計するためのベストプラクティスについて説明します。

アクセシビリティ属性

アクセシブルなウェブエクスペリエンスを構築することは、多くの場合、Accessible Rich Internet Applications (ARIA)属性を設定して、そうでなければ欠落しているセマンティックな意味を提供することを伴います。 属性バインディングテンプレート構文を使用して、アクセシビリティ関連属性の値を制御します。

ARIA属性とプロパティ

AngularでARIA属性にバインドする場合、他のHTML属性と同様に直接使用できます。

<button [aria-label]="myActionLabel">…</button>

静的ARIA属性は通常のHTML属性として機能します。

<button aria-label="Save document">…</button>

HELPFUL: 慣習的に、HTML属性は小文字の名前を使用します (tabindex)、一方プロパティはcamelCaseの名前を使用します (tabIndex)。

一部のARIAパターンは、構造化された値(例: Element 参照のコレクション)を受け入れるDOM APIまたはディレクティブ入力を公開します。そのような場合は、標準のプロパティバインディングを使用して、基礎となる関係を同期させます。

@Component({  template: `    <h2 #dialogTitle>Attention</h2>    <p #dialogDescription>Please review your answers before continuing.</p>    <section      role="dialog"      [ariaLabelledByElements]="[dialogTitle, dialogDescription]">      <ng-content />    </section>`,})export class ReviewDialog {}

ここで [ariaLabelledByElements] は要素の配列を受け入れるため、プロパティバインディングは、テンプレートデータが変更されるたびに要素参照を最新の状態に保ちます。

ARIA属性構文の概要については、バインディングガイドを参照してください。

Angular UIコンポーネント

Angularチームが保守しているAngular Materialライブラリは、完全なアクセシビリティを目指した、再利用可能なUIコンポーネントのスイートです。 Component Development Kit (CDK)には、アクセシビリティのさまざまな領域をサポートするためのツールを提供するa11yパッケージが含まれています。 例えば:

  • LiveAnnouncerは、aria-live領域を使用して、スクリーンリーダーユーザーにメッセージを発表するために使用されます。 aria-live領域の詳細については、W3Cのドキュメントを参照してください。

  • cdkTrapFocusディレクティブは、Tabキーのフォーカスを要素内に閉じ込めておきます。 モーダルダイアログなど、フォーカスを制限する必要があるコンポーネントのアクセシブルなエクスペリエンスを作成するために使用します。

これらのツールやその他のツールの詳細については、Angular CDKアクセシビリティの概要を参照してください。

ネイティブ要素の拡張

ネイティブHTML要素は、アクセシビリティにとって重要な、いくつかの標準的な相互作用パターンを捉えています。 Angularコンポーネントを作成する際には、サポートされている動作を再実装するのではなく、可能な限りこれらのネイティブ要素を直接再利用する必要があります。

たとえば、新しい種類のボタンのカスタム要素を作成するのではなく、ネイティブ<button>要素で属性セレクターを使用するコンポーネントを作成します。 これは、<button><a>に最もよく適用されますが、他の多くのタイプの要素で使用できます。

このパターンの例は、Angular Materialで見ることができます: MatButtonMatTabNav、およびMatTable

ネイティブ要素のためのコンテナの使用

ネイティブ要素を使用するには、コンテナ要素が必要になる場合があります。 たとえば、ネイティブの<input>要素は子を持たせることができないため、カスタムテキスト入力コンポーネントは<input>を余分な要素でラップする必要があります。 <input>をカスタムコンポーネントのテンプレートに含めるだけで、コンポーネントのユーザーは<input>要素に任意のプロパティや属性を設定できません。 代わりに、コンテンツプロジェクションを使用してコンポーネントのAPIにネイティブコントロールを含む、コンテナコンポーネントを作成します。

MatFormFieldは、このパターンの例として見ることができます。

ケーススタディ: カスタムプログレスバーの構築

次の例は、ホストバインディングを使用してアクセシビリティ関連属性を制御することで、プログレスバーをアクセシブルにする方法を示しています。

  • コンポーネントは、標準のHTML属性roleとARIA属性の両方を持つ、アクセシビリティ対応の要素を定義します。 ARIA属性aria-valuenowは、ユーザーの入力にバインドされます。
  • テンプレートでは、aria-label属性により、コントロールはスクリーンリーダーにとってアクセシブルになります。

ルーティング

ナビゲーション後のフォーカス管理

UIにおけるフォーカスの追跡と制御は、アクセシビリティを考慮する上で重要な要素です。 Angularルーティングを使用する場合は、ページナビゲーション時にページフォーカスがどこに移動するかを決定する必要があります。

視覚的な手がかりだけに頼らないようにするには、ルーティングコードがページナビゲーション後にフォーカスを更新することを確認する必要があります。 NavigationEndイベントをRouterサービスから使用して、フォーカスを更新するタイミングを把握します。

次の例は、ナビゲーション後にDOM内のメインコンテンツヘッダーを見つけてフォーカスする方法を示しています。

router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe(() => {  const mainHeader = document.querySelector('#main-content-header');  if (mainHeader) {    mainHeader.focus();  }});

実際のアプリケーションでは、フォーカスを受け取る要素は、特定のアプリケーションの構造とレイアウトによって異なります。 フォーカスされる要素は、ユーザーを、ちょうどビューにルーティングされたメインコンテンツにすぐに移動できる位置に置く必要があります。 ルート変更後にフォーカスがbody要素に戻るような状況は避ける必要があります。

RouterLinkActiveなど、アクティブなRouterLink要素に適用されるCSSクラスは、アクティブなリンクを視覚的に識別するための手がかりを提供します。 残念ながら、視覚的な手がかりは、盲人または視覚障害のあるユーザーには役立ちません。 要素にaria-current属性を適用すると、アクティブなリンクを識別するのに役立ちます。 詳細については、Mozilla Developer Network (MDN) aria-currentを参照してください。

RouterLinkActiveディレクティブは、リンクがアクティブになるとaria-currentを指定された値に設定するariaCurrentWhenActive入力を提供します。

次の例は、アクティブなリンクにactive-pageクラスを適用する方法と、アクティブになったときにaria-current属性を"page"に設定する方法を示しています。

<nav>  <a routerLink="home"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    Home  </a>  <a routerLink="about"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    About  </a>  <a routerLink="shop"      routerLinkActive="active-page"      ariaCurrentWhenActive="page">    Shop  </a></nav>

遅延読み込み

Angularの@deferブロックを使用してコンテンツを遅延読み込みする場合、支援技術を使用するユーザーへのアクセシビリティの影響を考慮してください。 スクリーンリーダーは、遅延コンポーネントが読み込まれたときにコンテンツの変更を自動的に通知しない場合があり、ユーザーが新しいコンテンツに気づかない可能性があります。

遅延コンテンツの変更が適切に通知されるようにするには、適切なARIAライブ領域を持つ要素で@deferブロックをラップします。 詳細なガイダンスと例については、deferガイドのアクセシビリティセクションを参照してください。

詳細情報

書籍

  • "A Web for Everyone: Designing Accessible User Experiences," Sarah Horton and Whitney Quesenbery
  • "Inclusive Design Patterns," Heydon Pickering