アクセシブルなダイアログの実装からフォーカス管理を学ぶ


前回の記事に引き続き、アクセシビリティについて書きます、Gaji-Labo でフロントエンドエンジニアをしている上條(mk-0A0)です。
前回は『APG』という ARIA の定義をもとにしたアクセシブルな UI を学べるガイドについて書きました。

APG には Patterns と呼ばれる アクセシブルな UI のパターン集があります。その中の1つであるダイアログの解説を読んだ際にフォーカス管理についての学びが多かったため、アウトプットがてら整理してみたいと思います。

また、APG は WCAG や ARIA のような規約やデザインシステムの役割は持っておらず、あくまでアクセシビリティの概念を学ぶためのものになっています。そのため紹介されている実装が絶対的な正ではないことをご了承ください。
参考:Introduction | APG | WAI | W3C

ダイアログの要件

まずは About This Pattern のセクションからダイアログの要件を改めて確認します。
参考:Dialog (Modal) Pattern | APG | WAI | W3C

  • ウィンドウや他のダイアログの上に重なるウィンドウ
  • 下のウィンドウは不活性になり、アクティブなダイアログから外側のコンテンツにはアクセスできない
  • Tab/Shift+Tab でダイアログ内のフォーカス移動が可能
  • ダイアログを閉じることなく外側へのフォーカス移動はできない

キャプチャのようなよく見る一般的な UI ですね。

Tailwind CSS Modal Dialogs – Official Tailwind UI Components

余談ですが、本記事では「モーダル」ではなく「ダイアログ」というワードを使っています。この2つには違いがあるのですが、皆さんはご存知でしょうか?
「ダイアログ」は表示される要素本体(キャプチャの白背景部分)を指しているのに対し、「モーダル」はソシオメディアによると モードがある状態。つまり、システムが特定の機能の使用に制限された状態。 とされています。(参考:ソシオメディア | モーダル
例えばダイアログが表示されている場合「モーダルなダイアログ」という表現が正確になります。(そのため「モーダルダイアログ」を「モーダル」と言うなと弊社の役員原田が言っていました)

WCAG で求められるフォーカスの挙動

ダイアログの要件はお分かりいただけたと思いますが、ではアクセシブルなフォーカスの挙動とはどういったものでしょうか?WCAG 2.2 ではフォーカスに関する項目が7つあります。その中からレベルA・AAの項目5つをピックアップしました。

参考:Web Content Accessibility Guidelines (WCAG) 2.2 (日本語訳)

最低限達成するべきであるレベルAの挙動は、操作可能なフォーカスの順序にすることとフォーカスを受け取ったときにコンテキストの変化を起こさないこととされています。「コンテキストの変化」とはフォームの送信や新しいウィンドウを開くなどの挙動を指します。

またレベルAAの中では、今回のケースの場合フォーカスの可視化が特に重要だと感じています。フォーカスはもともと可視化されていますが、それを取り除いたり outline や border で実装するのは推奨されていません。

ダイアログにおけるフォーカスの挙動

意識したいフォーカスの挙動を踏まえたうえで、APG に掲載されているダイアログの Example を見てみましょう。Example で使われるダイアログは4つあります。
Modal Dialog Example | APG | WAI | W3C

1. Add Delivery Address

Add Delivery Address ボタンを押すと表示されるダイアログです。

Add Delivery Addressダイアログのキャプチャ

このダイアログの初期フォーカスは、ユーザーが最初に操作すると考えられる input の “Street” に当たります。そこから順番に後続の input、ボタンと移動し、最後のインタラクション要素である Cancel ボタンまで来たら1番最初の input(Street) に戻ります。これは「ダイアログを閉じることなく外側へのフォーカス移動はできない」というダイアログの要件を満たしており、フォーカストラップと呼ばれます。
参考:フォーカストラップとは? 〜アクセシブルなモーダル〜

そして Cancel ボタンでダイアログを閉じると、ダイアログを開いた Add Delivery Address ボタンにフォーカスが戻ります。ダイアログを閉じるなどの1つ前の状態に戻るアクションがあった時、フォーカスはそのアクションを起こした要素に戻るのが基本の挙動となります。

2. Verification Result

Add Delivery Address ダイアログの Verify Address ボタンを押すと表示されるダイアログです。

Verification Resultダイアログのキャプチャ

ぱっと見でお分かりかと思いますが、他のダイアログと比べてコンテンツ量が多いです。このダイアログを実際に開いた時、ボタン類は見切れて表示されていないと思います。そのため初期フォーカスが少し特殊で、一番最初のインタラクション要素であるテキストリンクではなくはじめの段落になっています。

フォーカスはインタラクション要素に付与されるのが一般的ですが、なぜこのような実装になっているのでしょうか?先ほど少し触れましたが、ボタン類はファーストビューで見切れています。その状態でボタン類に初期フォーカスを当てるとファーストビューでボタン類が表示されてしまい、逆にコンテンツ上部が見切れるためこのような手段が取られています。…といった内容がこのダイアログに書かれているので、コンテンツ量が多いダイアログのフォーカス位置とデザインの注意点について詳しく知りたい方はぜひ読んでみてください。

そして Close ボタンは Add Delivery Address ダイアログの Verify Address ボタンにフォーカスが戻ります。

3. Address Added

Add Delivery Address ダイアログの Add ボタンを押すと表示されます。

Address Addedダイアログのキャプチャ

OK ボタンでダイアログを閉じると Add Delivery Address ボタンにフォーカスが戻ります。

このダイアログの場合、初期フォーカスはテキストリンクではなく OK ボタンです。順序的にはテキストリンクにフォーカスを当てるのが適切に見えますが、多くの人はリンクに飛ぶより OK ボタンでダイアログを閉じると考えられるためこのような実装になっています。
WCAG で言われている「操作可能なフォーカス順序」とは順番通りという意味ではなく、ユーザーがどういうアクションをするかという観点も含まれていそうだと感じました。

そしてリンクに飛ぶと後述する End of the Road! ダイアログが開き、閉じるとテキストリンクにフォーカスが当たった状態になります。

4. End of the Road!

Address Added ダイアログや Verification Result ダイアログなど、複数箇所からアクセスできるダイアログです。

End of the Road!ダイアログのキャプチャ

Close ボタンでダイアログを閉じ、前のダイアログに戻ります。フォーカスは自身を開いたボタンやリンクに戻ります。
先述したとおり複数のダイアログからアクセスできるため、ダイアログを閉じてフォーカスを戻す際にどのインタラクション要素から開かれたかを取得するひと手間の工夫がされているのが分かります。

まとめ

フォーカスは気にしていましたが深い理解とまでは至ってなかったので、調べてみると想像以上に工夫できることがたくさんあって学びが多かったです。文中でフォーカストラップについて少し触れましたが、調べる過程で「キーボードトラップ」と混ざってしまい混乱していました。ちなみにキーボードトラップとは、例えばダイアログの閉じるボタンにフォーカスが当たらないことでキーボード操作ではダイアログを閉じられず、閉じるにはマウスしか使えないという状態だそうです。(参考:達成基準 2.1.2: キーボードトラップなしを理解する
今回キーボードトラップについて文中では触れませんでしたが、キーボードトラップをしないことはレベルAに設定されているので、より一層意識して不注意によってアクセシビリティを損なわないように気をつけなければと思いました。

Gaji-Labo はアクセシビリティの知見がある・アクセシビリティに興味があるエンジニア、デザイナーの方とお話できる機会を作りたいと思っています。興味のある方、ぜひカジュアル面談でお話ししましょう!

Gaji-Laboでは、 Next.js 経験が豊富なフロントエンドエンジニアを募集しています

弊社では Next.js の知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違う Gaji-Labo を味わいに来ませんか?

Next.js の設計・実装を得意とするフロントエンドエンジニア募集要項

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!


投稿者 Kamijo Momoka

フロントエンドエンジニア。
HTML/CSS/JavaScript/WordPressでのサイト制作からNext.js/TypeScriptなどを使ったWebアプリ開発、FigmaでのUIデザインまで広く経験しています。 デザインエンジニアと名乗るのが夢です。