フォームのマークアップについて、アクセシビリティを考慮したコードを考えてみます。
対応前
まずは特に意識しないでマークアップしてみます。
<form action=""> <div class="form-item"> <div class="form-item_key"> お名前<span class="required">(必須)</span> </div> <div class="form-item_val"> <input type="text" name="name" /> </div> </div> <div class="form-item"> <div class="form-item_key"> 電話番号 </div> <div class="form-item_val"> <input type="tel" name="tel" placeholder="09000000000" /> <p class="form-item_notes">ハイフンを含めず、半角数字のみで入力してください。</p> </div> </div> <div class="form-item"> <div class="form-item_key"> 性別<span class="required">(必須)</span> </div> <div class="form-item_val"> <input type="radio" name="gender" id="male" value="" /> <label for="male">男性</label> <input type="radio" name="gender" id="female" value="" /> <label for="female">女性</label> </div> </div> <div class="form-item"> <div class="form-item_key"> 好み </div> <div class="form-item_val"> <input type="checkbox" name="favorite[]" id="toru" value="浅倉透" /> <label for="toru">浅倉透</label> ~略~ </div> </div> <div class="form-item"> <div class="form-item_key"> 地域 </div> <div class="form-item_val"> <select name="area"> <option value="">----------</option> <option value="北海道">北海道</option> ~略~ </select> </div> </div> <div class="form-item"> <div class="form-item_key"> メッセージ<span class="required">(必須)</span> </div> <div class="form-item_val"> <textarea name="message"></textarea> </div> </div> <button>送信</button> </form>
これでフォームのマークアップができました。
対応前のフォームのデモページ
このフォームを元に改善を進めてみます。
テキスト入力・セレクトボックスとラベルの紐づけ
まずはフォーム要素とラベルの紐づけを行ってみます。
1行テキストとテキストエリア、セレクトボックスを変更してみます。
<form action=""> <div class="form-item"> <div class="form-item_key"> <label for="name">お名前<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <input type="text" name="name" id="name" /> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="tel">電話番号</label> </div> <div class="form-item_val"> <input type="tel" name="tel" id="tel" placeholder="09000000000" /> <p class="form-item_notes">ハイフンを含めず、半角数字のみで入力してください。</p> </div> </div> <div class="form-item"> <div class="form-item_key"> 性別<span class="required">(必須)</span> </div> <div class="form-item_val"> <input type="radio" name="gender" id="male" value="" /> <label for="male">男性</label> <input type="radio" name="gender" id="female" value="" /> <label for="female">女性</label> </div> </div> <div class="form-item"> <div class="form-item_key"> 好み </div> <div class="form-item_val"> <input type="checkbox" name="favorite[]" id="toru" value="浅倉透" /> <label for="toru">浅倉透</label> ~略~ </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="area">地域</label> </div> <div class="form-item_val"> <select name="area" id="area"> <option value="">----------</option> <option value="北海道">北海道</option> ~略~ </select> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="message">メッセージ<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <textarea name="message" id="message"></textarea> <p class="form-item_notes">500文字以内で入力してください。</p> </div> </div> <button>送信</button> </form>
ラベル部分にlabel要素とfor属性を設定して、フォーム要素にはid属性を追加しました。
テキスト入力・セレクトボックスとラベルの紐づけのデモページ
スクリーンリーダーのPC-Talkerで確認したところ、対応前と比べて以下のようにラベルが紐づいた読み上げに変わりました。
- お名前のinput要素にフォーカスが当たった時は、対応前時点では「文字入力」のみでしたが、対応後は「お名前(必須)の 文字入力」となりました。
- 電話番号のinput要素の対応前時点では「09000000000の 文字入力」とplaceholderを使った内容でしたが、対応後は「電話番号の 文字入力」となりました。
- 地域のセレクトボックスの対応前時点では「文字入力」のみでしたが、対応後は「地域の 選択 ———-」となりました。
- メッセージのテキストエリアの対応前時点では「選択 ———-」でしたが、対応後は「メッセージ(必須)の 文字入力」となりました。
ラジオボタン・チェックボックスとラベルの紐づけ
フォーム要素とラベルの紐づけの続きで、ラジオボタンとチェックボックスを変更します。
ただしラジオボタンとチェックボックスは項目値との紐づけでlabel要素を使っているので、グループ全体をfieldset要素で囲った上で、ラベルをlegend要素で囲みます。
<form action=""> <div class="form-item"> <div class="form-item_key"> <label for="name">お名前<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <input type="text" name="name" id="name" /> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="tel">電話番号</label> </div> <div class="form-item_val"> <input type="tel" name="tel" id="tel" placeholder="09000000000" /> <p class="form-item_notes">ハイフンを含めず、半角数字のみで入力してください。</p> </div> </div> <fieldset class="form-item"> <legend class="form-item_key"> 性別<span class="required">(必須)</span> </legend> <div class="form-item_val"> <input type="radio" name="gender" id="male" value="" /> <label for="male">男性</label> <input type="radio" name="gender" id="female" value="" /> <label for="female">女性</label> </div> </fieldset> <fieldset class="form-item"> <legend class="form-item_key"> 好み </legend> <div class="form-item_val"> <input type="checkbox" name="favorite[]" id="toru" value="浅倉透" /> <label for="toru">浅倉透</label> ~略~ <label for="hinana">市川雛菜</label> </div> </fieldset> <div class="form-item"> <div class="form-item_key"> <label for="area">地域</label> </div> <div class="form-item_val"> <select name="area" id="area"> <option value="">----------</option> <option value="北海道">北海道</option> ~略~ </select> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="message">メッセージ<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <textarea name="message" id="message"></textarea> <p class="form-item_notes">500文字以内で入力してください。</p> </div> </div> <button>送信</button> </form>
ラベルを囲うlegend要素は、fieldset要素の子要素に配置しないといけないようなので、注意してください。
ラジオボタン・チェックボックスとラベルの紐づけのデモページ
PC-Talkerで確認した際の変更は以下の通りです。
- 性別のラジオボタンにフォーカスが当たった時は、対応前時点では「男性の 選択」でしたが、対応後は「性別(必須)の 選択 男性」となりました。
- 好みのチェックボックスの対応前時点では「浅倉透の 切替 チェックなし」でしたが、対応後は「好みの 切替 浅倉透 チェックなし」となりました。
フォーム要素と説明の紐づけ
次にフォーム要素と説明の紐づけを行ってみます。
今回の例でいうと、電話番号(1行テキスト)とメッセージ(テキストエリア)の.form-item_notes要素になります。
<form action=""> <div class="form-item"> <div class="form-item_key"> <label for="name">お名前<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <input type="text" name="name" id="name" /> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="tel">電話番号</label> </div> <div class="form-item_val"> <input type="tel" name="tel" id="tel" aria-describedby="notes-tel" placeholder="09000000000" /> <p id="notes-tel" class="form-item_notes">ハイフンを含めず、半角数字のみで入力してください。</p> </div> </div> <fieldset class="form-item"> <legend class="form-item_key"> 性別<span class="required">(必須)</span> </legend> <div class="form-item_val"> <input type="radio" name="gender" id="male" value="" /> <label for="male">男性</label> <input type="radio" name="gender" id="female" value="" /> <label for="female">女性</label> </div> </fieldset> <fieldset class="form-item"> <legend class="form-item_key"> 好み </legend> <div class="form-item_val"> <input type="checkbox" name="favorite[]" id="toru" value="浅倉透" /> <label for="toru">浅倉透</label> ~略~ </div> </fieldset> <div class="form-item"> <div class="form-item_key"> <label for="area">地域</label> </div> <div class="form-item_val"> <select name="area" id="area"> <option value="">----------</option> <option value="北海道">北海道</option> ~略~ </select> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="message">メッセージ<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <textarea name="message" id="message" aria-describedby="notes-message"></textarea> <p id="notes-message" class="form-item_notes">500文字以内で入力してください。</p> </div> </div> <button>送信</button> </form>
フォーム要素にaria-describedby属性を設定して、説明をしている要素にid属性を追加しました。
フォーム要素と説明の紐づけのデモページ
今回は説明している要素がラベルと離れていた(フォーム要素の下にあった)のでこの対応になりましたが、例えばラベルの横に説明のテキストがある場合などは、label要素(ラジオボタンやチェックボックスの場合はlegend要素)内に説明のテキストを含める形でも問題ありません。
今回でいうと「必須」というテキストはフォームを説明するものになるので、label要素(legend要素)の中に含めるようにしています。
PC-Talkerで確認した際の変更は以下の通りです。
- 電話番号の変更前は「電話番号の 文字入力」でしたが、対応後は「電話番号の 文字入力 ハイフンを含めず、半角数字のみで入力してください。」となりました。
- メッセージの変更前は「メッセージ(必須)の 文字入力」でしたが、対応後は「メッセージ(必須)の 文字入力 500文字以内で入力してください。」となりました。
必須要素の指定
必須要素に対してaria-required属性の指定を行います。
今回の例だとlabel要素内に「必須」というテキストが含まれているので読み上げ上は問題なさそうですが、例えば「必須」の代わりに「*」になっているなど、場合によってはこの対応が必要になります。
<form action=""> <div class="form-item"> <div class="form-item_key"> <label for="name">お名前<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <input type="text" name="name" id="name" aria-required="true" /> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="tel">電話番号</label> </div> <div class="form-item_val"> <input type="tel" name="tel" id="tel" aria-describedby="notes-tel" placeholder="09000000000" /> <p id="notes-tel" class="form-item_notes">ハイフンを含めず、半角数字のみで入力してください。</p> </div> </div> <fieldset class="form-item"> <legend class="form-item_key"> 性別<span class="required">(必須)</span> </legend> <div class="form-item_val"> <input type="radio" name="gender" id="male" value="" /> <label for="male">男性</label> <input type="radio" name="gender" id="female" value="" /> <label for="female">女性</label> </div> </fieldset> <fieldset class="form-item"> <legend class="form-item_key"> 好み </legend> <div class="form-item_val"> <input type="checkbox" name="favorite[]" id="toru" value="浅倉透" /> <label for="toru">浅倉透</label> ~略~ </div> </fieldset> <div class="form-item"> <div class="form-item_key"> <label for="area">地域</label> </div> <div class="form-item_val"> <select name="area" id="area"> <option value="">----------</option> <option value="北海道">北海道</option> ~略~ </select> </div> </div> <div class="form-item"> <div class="form-item_key"> <label for="message">メッセージ<span class="required">(必須)</span></label> </div> <div class="form-item_val"> <textarea name="message" id="message" aria-describedby="notes-message" aria-required="true"></textarea> <p id="notes-message" class="form-item_notes">500文字以内で入力してください。</p> </div> </div> <button>送信</button> </form>
PC-Talkerで確認した際の変更は以下の通りです。
- お名前の変更前は「お名前(必須)の 文字入力」でしたが、対応後は「お名前(必須) 必須 の 文字入力」となりました。
- メッセージの変更前は「メッセージ(必須)の 文字入力」でしたが、対応後は「メッセージ(必須) 必須 の 文字入力 500文字以内で入力してください。」となりました。
コメントが承認されるまで時間がかかります。