2019年6月1日にCSSNite主催のwebアクセシビリティの学校に参加してきました。
ここでは詳細は記載しませんが、マシンリーダブルなコードを書くことへの意識が高まる1日でした。
アンケートの質問欄にフォームのコーディングについて質問を書いたところ、フォローアップで質問にご回答頂きました。
(質問採用されるのなかなか嬉しいですよね)
そこでfiledset
とlegend
というタグを知ったので、その使い方と調べていく過程で疑問に思ったテーブルレイアウトへの組み込み方をまとめていきます。先にお伝えしておくと、table
タグでは使えませんでした。
質問と回答内容
【質問】
フォームで氏名を入力する場面で、「氏名:姓[ ]名[ ]」のような場合、labelは姓と名だけにつければいいでしょうか?
【ご回答】
「姓」と「名」をlabel要素でマークアップするのに加えて、全体をfieldset要素で囲んで、「氏名」をlegend要素でマークアップすることで、全体をグループ化できます。
参考:H71: fieldset 要素及び legend 要素を使用して、フォームコントロールのグループに関する説明を提供する|WCAG 2.0 達成方法集
filedset
…そんなタグがあるのですね。恥ずかしながら知りませんでした。
もちろんlegend
タグも知りませんでした。
そこで、頂いた参考の他にいくつか情報をあたり自分なりに使い方を整理してみようと思います。
fieldsetとlegendの使い方
HTMLクイックリファレンスのfieldsetの項目には下記の記載がありました。
fieldset
タグは、フォームの入力項目をグループ化する際に使用します。fieldset~fieldset
の中に配置されたinput
・select
・textarea
等のフォーム部品がグループ化され、一般的なブラウザではボーダーで囲まれて表示されます。
フォーム部品のグループにキャプション(タイトルや説明)を付ける場合には、
fieldset~fieldset
の中の 最初のlegend
で指定します。
また、disabled属性・form属性・name属性についても記載がありました。
内容をまとめると、
fieldset
を使ってフォームの項目をグループ化- タイトルや説明をつけるのに
legend
を使う - disabled属性でグループ単位で無効化できる
form
タグの外に配置するときはform属性とform
のidを合わせて紐付けられる- name属性はスクリプトからの操作用に使う
なお、disabled属性・form属性・name属性はhtml5になって追加されたらしいです。
「氏名:姓[ ]名[ ]」をfieldsetを使ってコーディング
fieldset
の使い方がわかったところで、「氏名:姓[ ]名[ ]」という入力フォームを実際にコーディングしてみました。
form内にfieldsetを設置したパターン
See the Pen fieldset inside of form by Yuki Tomioka (@yuki-tomioka) on CodePen.
label
とinput
の紐付けはネストせずにfor属性とidを使ってもいいですね。
formの外にfieldsetを設置したパターン
See the Pen fieldset outside of form by Yuki Tomioka (@yuki-tomioka) on CodePen.
fieldsetはtableやdlの中で使えるのか
fieldset
の使い方はわかったのですが、ここでふとした疑問が浮かびました。
フォームのコーディングをするときtable
やdl
タグを使うことが多いのですが、この場合fieldset
はどこに入れればいいだろうかという疑問です。
例えば下記のようなフォームがあったとします。
See the Pen form e.g. by Yuki Tomioka (@yuki-tomioka) on CodePen.
legend
はth
内で氏名を囲えばよさそうですが、fieldset
はどこに入れればいいのでしょうか。
グループ化するという意味合いからtr
の中か外の気もしますが、入れ子のルールとして違うタグは入れられないはずです。
考えてもわからなかったので、実際にコードを書いてツールで検証を行いました。検証にはNu Html Checkerを使いました。
試してみたコードその1
fieldset
でtr
を囲ったパターン
<form>
<table>
<fieldset>
<tr>
<th>
<legend>氏名</legend>
</th>
<td>
<label for="family-name">姓</label>
<input type="text" id="family-name">
<label for="last-name">名</label>
<input type="text" id="last-name">
</td>
</tr>
</fieldset>
</table>
</form>
検証結果
はい。予想通りがっつりエラーでした。
試してみたコードその2
fieldset
をtr
の中に入れたパターン
<form>
<table>
<tr>
<fieldset>
<th>
<legend>氏名</legend>
</th>
<td>
<label for="family-name">姓</label>
<input type="text" id="family-name">
<label for="last-name">名</label>
<input type="text" id="last-name">
</td>
</fieldset>
</tr>
</table>
</form>
検証結果
はい。こちらもエラーでした。
fieldsetをtableの中で使えるのか?の結論
結論は使えません!
tableタグを使ってフォームを作る場合、構造上入れる場所がないのでtable
の中でfieldset
を使うことができません。また、dl
も直下に入れられるのはdt
とdd
のみなので同じようにfieldset
を使うことはできません。
fieldsetを使ってテーブルレイアウトのフォームを作る
テーブルレイアウトのフォームを作るときはどうすればいいのか、色々と検索していると次の記事に出会いました。
CSSが効かない!?fieldset要素でも簡単にテーブルレイアウトを実現できるdisplay: contents;
入力フォームでは、1つのキャプションとフォームコントロールのグループを横並びに配置するために、度々table要素が使われているように感じます。レイアウトを目的としてtable要素を利用すると、アクセシビリティ周りで発生するいくつかの問題を解決していかないといけません。
(上記記事本文より)
そうそうまさにこれです。
詳細はリンク先の記事を参照頂ければと思いますが、概要としては下記の通りです。
table
は使わずにCSSでテーブルレイアウトを作成するfieldset
にはdisplay:table
が効かないfieldset
にdisplay:contents
を当ててdisplay上の関係性から切り離す- 他の要素に
display:table
やtable-row
、table-cell
を当ててテーブルレイアウトを実現する
実際のコードでみた方がわかりやすいかもしれません。
NGパターン
See the Pen 【NG】fieldset use in talbe layout by Yuki Tomioka (@yuki-tomioka) on CodePen.
OKパターン
See the Pen fieldset use in talbe layout by Yuki Tomioka (@yuki-tomioka) on CodePen.
display:contents
プロパティ自体の解説や他の使いどころはColissさんの[CSS]「display: contents;」がすごい便利!ラッパーを使った実装が大きく変わるこれからのテクニックがわかりやすかったです。
display:contentsの罠
やっと回答に辿りついたと思ったのですが、こんな記述が
ただ、display: contents;には注意点があります。サポートしているブラウザがまだ十分とは言えないというのもそうなのですが、本来この値はセマンティクスに影響を及ぼさないとされているところ、実はdisplay: contents;な要素がまるでdisplay: none;のようにアクセシビリティツリーから無視されてしまうというバグがモダンブラウザで確認されているのです。
そこで、Can I useで調べてみました。
IE、Edgeでは使えず、他のブラウザでも一部にバグがあるようです(2019年6月24日時点)。
WAI-ARIAのrole=”group”を使う
社内ツールなど使用するブラウザを限定することが可能な状況であればfiedlset
とdisplay:contents
の組み合わせで対応できますが、一般向けのwebサイトなど多くの場合はIEやEdgeにも対応する必要があると思います。
その点を考えるとfieldset
の代わりにWAI=ARIAのrole=”group”を使ってdiv role="group"
とし関連付けをするのが多くのケースで使えるコーディングとなりそうです。
まとめ
fieldset
を使うことでフォームのパーツをグループ化できマシンリーダブル性があげられるlegend
を合わせて使うことで何のグループなのかを説明できるfieldset
を使ってテーブルレイアウトを作るときはtable
は使えず、display:contents
を使う- 多くのブラウザに対応するにはWAI=ARIAの
role="group"
を使う
WAI-ARIAを使ってコーディングをしていない場合は、導入のための学習コストや社内理解などが必要になるというコーディングとは別の課題が出てきそうですね。
WAI-ARIAの基本として必要な時だけ使うとある通り、HTMLとCSSのみで実装できるよう各種ブラウザでfiledset
の扱いやdisplay:contents
の実装やバグフィックスが進むといいですね。