アクセシビリティを考慮したモーダルウインドウを作ってみた
アクセシビリティ、配慮していますか? 視覚障害の方に配慮したモーダルウインドウ付きのページを作る機会があったので、忘れないうちにメモしておこうと思います。
01シンプルなモーダルウインドウ
jQueryとcssで簡単なモーダルウインドウを作る
まずはシンプルなモーダルウインドウの実装から。簡単に済ますために今回はjQueryで。
モーダルウインドウにかかわる部分だけ抜粋(余計なクラスやスタイルなどは省いて)して紹介します。
HTML
<div class="main">
<p><a href="#modal01" class="link_modal">モーダルウインドウ1</a></p>
<p><a href="#modal02" class="link_modal">モーダルウインドウ2</a></p>
<p><a href="#modal03" class="link_modal">モーダルウインドウ3</a></p>
</div>
<div id="modal01" class="modal_target">
<p>モーダルウインドウ1の中身です。</p>
</div>
<div id="modal02" class="modal_target">
<p>モーダルウインドウ2の中身です。</p>
</div>
<div id="modal03" class="modal_target">
<p>モーダルウインドウ3の中身です。</p>
</div>
<div id="modal">
<div id="modal_inner"></div>
<div id="modal_close">モーダルウインドウを閉じる</div>
</div>
javascript
//モーダルウインドウを開く
$('.link_modal').on('click', function(){
var target= $(this).attr('href');
$('#modal_inner').html($(target).html());
$('#modal').addClass('__open');
$('body').addClass('__fixed');
});
//モーダルウインドウを閉じる
$('#modal_close').on('click', function(){
$('#modal_inner').empty();
$('#modal').removeClass('__open');
$('body').removeClass('__fixed');
});
CSS
/* モーダルウインドウの枠と中身は隠しておく */
#modal,
.modal_target {
display: none;
}
/* モーダルウインドウを開いたとき */
#modal.__open {
display: block;
}
body.__fixed {
overflow: hidden;
}
/* モーダルウインドウの基本スタイル */
#modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: scroll;
z-index: 2;
}
まずはこれでシンプルなモーダルウインドウが出来ました。出来上がったモーダルウインドウのデモはこちらからご覧ください。それぞれ簡単に解説します。
HTMLでは、モーダルウインドウを開くリンクを3つ並べています。それぞれのリンク先はIDで指定したdivを開くようにしています。あらかじめ中身のdivはCSSでdisplay:none;
を指定しておきます。また、モーダルウインドウの枠にあたるdiv要素、#modalも非表示にしておきます。
リンクをクリックするとモーダルウインドウの子要素のdiv、#modal_innerの中にターゲットのhtmlをコピーします。そして、#modalに__openというクラス名を付与して、#modalを表示させています。
また、この時、body要素にも__fixedというクラスを付与しています。それは、モーダルを開いている際に背景のコンテンツをスクロールさせないための配慮です。
あとは必要に応じてモーダルウインドウにスタイルを追加してあげましょう。
02アクセシビリティ上の問題点
さて、シンプルなモーダルウインドウが完成しましたが、このままではアクセシビリティ上の問題があります。
意図する順番に読み上げできない
読み上げソフトを利用してみたことはありますか?読み上げソフトを使うと、キーボードの操作だけで、画面上のコンテンツを音声で読み上げることが出来ます。しかし、このままの状態のモーダルウインドウでは、意図したとおりに読み上げができません。何故でしょうか。
HTMLの構造を見てみてください。まず、「モーダルウインドウのリンク」が3つ並んでいますね。次に、ファーストビューでは隠れているコンテンツの、「モーダルウインドウの中身」が3つ続けて記述してあります。最後に、これも隠れているコンテンツである、「モーダルウインドウの枠」があります。
通常、読み上げソフトでは、キーボードを操作してフォーカスをうつし、フォーカスしている要素の内容を読み上げます。CSSで非表示にしているコンテンツには、フォーカスが移りません。そのため、初期表示では「モーダルウインドウのリンク」3つしか読み上げされません。
さて、リンクにフォーカスした状態でEnterを押すと、モーダルウインドウが開きます。この時、#modalにクラスを追加してdisplayをblockにするので、ようやくモーダルウインドウの中身がフォーカス可能になります。ただし、モーダルウインドウのHTML上の位置はあくまでページの一番下にあります。ということは、たとえば、「モーダルウインドウ1」を開いても、すぐにモーダルウインドウの中身が読み上げられることはありません。ページの情報が多くなれば多くなるほど、意図したとおりに内容を伝えることが難しくなってしまいますね。
03モーダルウインドウにフォーカス
上記の問題を解決するために、モーダルウインドウを開いたら、モーダルウィンドウの中身にフォーカスを移す処理を加えてあげましょう。
モーダルウインドウにフォーカス
javascript
$('#modal').addClass('__open').focus();
javascriptのfocus()
メソッドを使って、特定の要素にフォーカスを移すことが出来ます。
しかし、このままではfocus()
が効いていないと思います。
div要素をフォーカス可能に
実は、div等の要素にフォーカスしたいときはその要素にtabindexを設定する必要があります。
tabindex属性は、要素が入力フォーカスを持てることと、キーボードの順次ナビゲーションに加わるかどうか、どの位置に加わるかを示します。負の値の場合、ユーザーはキーボードを使用してフォーカスを与えることはできませんが、focus()メソッドでフォーカスを与えることが出来ます。
参考:MDN web docs
HTML
<div id="modal" tabindex="-1" role="dialog">
<div id="modal_inner"></div>
<div id="modal_close">モーダルウインドウを閉じる</div>
</div>
このようにすれば、focus()
メソッドが効くと思います。
デモはこちら。
モーダルウインドウを開いたことをユーザーに伝えよう
また、上記HTMLのコードでは、#modalにrole属性を追加しています。厳密にはモーダルウインドウでありdialogとは少し違うのですが、ページのコンテンツの他の部分から分離されたものとして識別する意味でつけています。
04モーダルウインドウ以外の要素へのフォーカスを無効化
さて、モーダルウインドウにjsでフォーカスさせることにより、幾分アクセシビリティが上がったかと思います。しかし、このままではモーダルウインドウの中身以外にもフォーカスを移すことができてしまいます。
area-hiddenを使ってフォーカスを無効にする
javascript
$('.main').attr('area-hidden','true');
area-hidden属性は、ユーザーエージェントに認識させたくない要素に指定するWAI-ARIA属性です。WAI-ARIA属性についてはこちらのサイトを参考に…。
モーダルウインドウを開いた際に、モーダルいウインドウ以外の要素のarea-hidden属性をtrueにすることで、フォーカスを無効にできますね。
05モーダルウインドウを閉じたら、リンク元にフォーカス
最後に、モーダルウインドウを閉じた時にも処理を追加します。モーダルウインドウはHTML上一番下に記述しているので、そのまま閉じてもフォーカスが元の場所に戻りませんね。なので、ここもjavascriptで制御すると良いでしょう。
ということで、完成版のHTMLとjavascriptはこちらです。
HTML
<div class="main">
<p><a href="#modal01" class="link_modal" id="link01">モーダルウインドウ1</a></p>
<p><a href="#modal02" class="link_modal" id="link02">モーダルウインドウ2</a></p>
<p><a href="#modal03" class="link_modal" id="link03">モーダルウインドウ3</a></p>
</div>
<div id="modal01" class="modal_target">
<p>モーダルウインドウ1の中身です。</p>
</div>
<div id="modal02" class="modal_target">
<p>モーダルウインドウ2の中身です。</p>
</div>
<div id="modal03" class="modal_target">
<p>モーダルウインドウ3の中身です。</p>
</div>
<div id="modal">
<div id="modal_inner"></div>
<div id="modal_close">モーダルウインドウを閉じる</div>
</div>
javascript
$('.link_modal').on('click', function(){
var target= $(this).attr('href'),
link = $(this).attr('id');
$('#modal_inner').html($(target).html());
$('#modal').addClass('__open').attr('area-hidden', 'false').focus().data('link',link);
$('.main').attr('area-hidden','true');
$('body').addClass('__fixed');
return false;
});
$('#modal_close').on('click', function(){
var link = $('#modal').data('link'),
target = '#' + link;
$(target).focus();
$('#modal_inner').empty();
$('#modal').removeClass('__open');
$('body').removeClass('__fixed');
});
デモはこちら。
リンク元にidを振って、モーダルを開いたときにリンク元のidを#modalのdata-link属性にメモしておくイメージです。これでうまく動くようになるかと思います。
この記事が役に立ったらシェアしてください!