WCAN mini 2016 Vol.1に参加したあと、アクセシブルなダイアログウィンドウを実装してみた

2016年6月4日(土) にベースキャンプ名古屋にてWCAN mini 2016 Vol.1 はアクセシビリティの勉強会が開催されました。role属性やaria属性の基本的な解説でしたが目から鱗なことがたくさん聞けました。



懇親会にて

自分は勉強会に参加する事はとても有意義だと思っています。というのも自分が何かを勉強する動機づけになるからです。中でも懇親会は自分のやる気を高めてくれる絶好の場ですので是非参加すべきです。
特に印象に残った事は、自分たちは専門家だから実装のプロは堀君がやりなさいということを植木さん、大藤さんに言われたことです。確かにこの分野はまだ力を入れている人が多くはないかもしれません。このとき自分の胸で闘志の炎が燃えるのを感じました。

そこで、まずはモーダルウィンドウを実装してみた

さて、ここからが本番です。まずは手始めにアクセシブルなダイアログウィンドウを実装してみました。以下がアクセシブルなダイアログウィンドウを実装する上で注意した点です。

  1. aria属性の付与
  2. ダイアログウィンドウ内でのtabフォーカス

1. aria属性の付与

aria属性と聞くと何か堅苦しく聞こえますが、要するにスクリーンリーダーにおけるCSSと考えればいいです。目が見えない人は聴覚に頼ってサイトからコンテンツを見つける必要があります。その際にaria属性がきちんと記述されていれば目の見えない人でもサイト上からコンテンツを見つけ出すことができます。MacではスクリーンリーダーであるVoice OverF5+[command]キーを同時に押して起動することができます。試してみてください。

aria-hidden

<div role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-description" class="dialog-bg js-dialog" aria-hidden="true" id="dialog">
<!-- ここにコンテンツ -->
</div>

まず、最初の状態ではaria-hidden属性をtrueにしてダイアログウィンドウをスクリーンリーダーに読み上げさせないようにしています。
ダイアログを出現させる際にaria-hiddenをfalseにしてはじめてスクリーンリーダーがダイアログの中身を読み上げてくれます。その際に同時にCSSも記述しておくと便利です。

.dialog-bg[aria-hidden="true"]{
	display: none;
}
.dialog-bg[aria-hidden="false"]{
	display: block;
}

aria-labelledby

aria-labelledby属性は要素に対してラベルを付ける事ができます。aria-labelledbyにIDを指定する事で要素についての説明を、該当するIDをもつ別の要素が行ってくれます。下記の例ではダイアログウィンドウの中のコンテンツに対してフォーカスが当たった時に「あなたはAccount Form Dialogの中のinput要素にフォーカス」しています。とVoice Overが読み上げてくれます。

<div role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-description" class="dialog-bg js-dialog" aria-hidden="true" id="dialog">
<h2 id="dialog-title">Account Form</h2>
</div>

Voice Overを使用すると実際に以下のように「Account Form Dialog First Name edit text」とDialogにちゃんと「Account Form」という名前が付与されているのが分かります。


aria-label="close"

またダイアログを閉じるボタンにはaria-labelにCloseという値を入れています。これによりVoice OverがClose Buttonとフォーカスが当たった際に読み上げてくれます。

<button type="button" class="dialog-close js-dialog-close" aria-label="close" title="close dialog button">X</button>

2. ダイアログウィンドウ内でのtabフォーカス

またアクセシビリティにはJavaScriptによる支援も大切です。

ダイアログウィンドウが閉じられた後のフォーカス位置

例えばダイアログが開いた際にはダイアログの中のフォーカスできる最初の要素にフォーカスが当たっていると嬉しいです。また、ダイアログウィンドウのクローズボタンが押されたときにダイアログウィンドウが押される前にフォーカスされていた本文中の要素にフォーカスし直す必要があります。document.activeElementでフォーカスが当たっている要素が取れるので、それを変数に格納しておけばクローズボタンが押された後、フォーカスが当たっていた要素にfocus()メソッドで再びフォーカスが当たるはずです。

var $active;
$btn.click(function(){
	$active = $(document.activeElement);
	$self.attr("aria-hidden",false);
	$firstInput.focus();
});
$(".js-dialog-close",$self).click(function(){
	$self.attr("aria-hidden","true");
	$active.focus();
});

ダイアログウィンドウ内でのフォーカスの循環

ダイアログウィンドウが開いている間、タブで移動する際にフォーカスが本文に移動してしまっては少し不便です。そこでダイアログ内の最初の要素と最後の要素を取得しておき、そこでタブキーが押されてもダイアログ外にフォーカスが移動しないように制御しましょう。この際にjQueryではfirst()、last()で最初の要素と最後の要素を取得できます。

var focusableElements = "a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]";
var $firstInput = $self.find(focusableElements).first();
var $lastInput = $self.find(focusableElements).last();
$firstInput.on('keydown', function (e) {
    if ((e.which === 9 && e.shiftKey)) {
        e.preventDefault();
        $lastInput.focus();
    }
});
$lastInput.on('keydown', function (e) {
   if ((e.which === 9 && !e.shiftKey)) {
       e.preventDefault();
       $firstInput.focus();
   }
});

最後に

皆さんに今回作ったダイアログウィンドウを触って頂けるようにデモを用意しました。デモは以下のリンクよりご覧頂けます。
ダイアログウィンドウのデモページ
今回の実装で得た知識はa-blog cmsの実装にも活かしていきたいですね。デフォルトのテーマを入れるだけでアクセシビリティ対策をしたことになるようなテーマの実装を目指します。


堀 悟大

アップルップル フロントエンドエンジニア。2014年高知大学理学部卒業。学生時代にHTML5のCanvas要素を使ってゲームを作っていたことでWeb全般に興味をもつ。アップルップル入社後はa-blog cmsを便利に使うための機能の実装や、HTML5の技術を使ったデジタルサイネージの実装を行う。趣味は英語。読むことも話すことも好き。

Home
Next entry →