fieldset要素とlegend要素を使用したことがあまりなかったのですが、少し前にこれらの要素にCSSを設定しようとして悩むことがあったので、設定方法についてメモ。
サンプルコード
まずfieldset要素とlegend要素を使用した際、特にCSSを設定しないとどういった見た目になるのか確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | < fieldset > < legend >好きな食べ物</ legend > < div > < input type = "checkbox" name = "check[]" id = "check-a" value = "鯖の味噌煮" > < label for = "check-a" >鯖の味噌煮</ label > < input type = "checkbox" name = "check[]" id = "check-b" value = "ビビンバ" > < label for = "check-b" >ビビンバ</ label > < input type = "checkbox" name = "check[]" id = "check-c" value = "鶏そぼろ丼" > < label for = "check-c" >鶏そぼろ丼</ label > < input type = "checkbox" name = "check[]" id = "check-d" value = "丼もの" > < label for = "check-d" >丼もの</ label > </ div > </ fieldset > |
fieldset要素内の項目が黒い枠で囲われ、legend要素が枠の左上に重なる形で配置されます。
この見た目で使用することはあまりないので、CSSのリセットを行ってみます。
1 2 3 4 5 6 7 8 9 10 11 | fieldset { min-width : 0 ; margin : 0 ; border : 0 ; padding : 0 ; } legend { width : 100% ; margin : 0 ; padding : 0 ; } |
これで見た目のリセットができました。
CSSをリセットするデモページ
次にCSSの装飾を行ってみます。
今回は項目名と入力フィールドを左右に並べるレイアウトにしてみます。
左右に並べる方法はいくつかありますが、まずはdisplay: flex; で試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | < form action = "" class = "form" > < div class = "form-parts" > < div class = "form-parts_key" > < label for = "name" >名前</ label > </ div > < div class = "form-parts_item" > < input type = "text" name = "name" id = "name" > </ div > </ div > < fieldset class = "form-parts" > < legend class = "form-parts_key" >好きな食べ物</ legend > < div class = "form-parts_item" > < input type = "checkbox" name = "check[]" id = "check-a" value = "鯖の味噌煮" > < label for = "check-a" >鯖の味噌煮</ label > < input type = "checkbox" name = "check[]" id = "check-b" value = "ビビンバ" > < label for = "check-b" >ビビンバ</ label > < input type = "checkbox" name = "check[]" id = "check-c" value = "鶏そぼろ丼" > < label for = "check-c" >鶏そぼろ丼</ label > < input type = "checkbox" name = "check[]" id = "check-d" value = "丼もの" > < label for = "check-d" >丼もの</ label > </ div > </ fieldset > </ form > |
.form-partsに対してdisplay: flex; を設定して横並びにします。
CSSは必要な部分のみ抜粋していますので、CSS全体はデモ内のコードをご確認ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | .form-parts { display : flex ; } .form-parts_key { width : 140px ; flex-shrink : 0 ; padding : 10px ; background : skyblue; } .form-parts_item { width : 100% ; padding : 10px ; background : orange; } |
これで名前の入力フィールドは意図したレイアウトになったのですが、fieldsetの場合は入力フィールドの要素が下に落ちてしまいました。
display: flex;を設定した場合のデモページ
chrome,Safari,Firefox,edgeで確認してみましたが、いずれも同じように崩れていました。
左右に並べる別の方法として、display: grid; も試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 | .form-parts { display : grid; grid-template-columns : 140px 1 fr; } .form-parts_key { padding : 10px ; background : skyblue; } .form-parts_item { padding : 10px ; background : orange; } |
この場合も名前の入力フィールドは問題ないのですが、fieldsetの場合は各ブラウザ共に意図したレイアウトになりませんでした。
display: grid;を設定した場合のデモページ
色々調べて試してみた結果、fieldsetにラッパー要素を追加してその要素にdisplay: flex あるいは grid を設定して、fieldsetにはdisplay: contents; を設定すると意図したレイアウトになりそうでした。
fieldsetにラッパー要素を追加して、class名を移動します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | < form action = "" class = "form" > < div class = "form-parts" > < div class = "form-parts_key" > < label for = "name" >名前</ label > </ div > < div class = "form-parts_item" > < input type = "text" name = "name" id = "name" > </ div > </ div > < div class = "form-parts" > < fieldset > < legend class = "form-parts_key" >好きな食べ物</ legend > < div class = "form-parts_item" > < input type = "checkbox" name = "check[]" id = "check-a" value = "鯖の味噌煮" > < label for = "check-a" >鯖の味噌煮</ label > < input type = "checkbox" name = "check[]" id = "check-b" value = "ビビンバ" > < label for = "check-b" >ビビンバ</ label > < input type = "checkbox" name = "check[]" id = "check-c" value = "鶏そぼろ丼" > < label for = "check-c" >鶏そぼろ丼</ label > < input type = "checkbox" name = "check[]" id = "check-d" value = "丼もの" > < label for = "check-d" >丼もの</ label > </ div > </ fieldset > </ div > </ form > |
fieldsetにdisplay: contents;を設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | .form-parts { display : flex ; } .form-parts > fieldset { display : contents; } .form-parts_key { width : 140px ; flex-shrink : 0 ; padding : 10px ; background : skyblue; } .form-parts_item { width : 100% ; padding : 10px ; background : orange; } |
これでfieldsetの方も横並びにできました。
display: flex;を設定した場合の対応後のデモページ
display: grid;の方も同様に試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | .form-parts { display : grid; grid-template-columns : 140px 1 fr; } .form-parts > fieldset { display : contents; } .form-parts_key { padding : 10px ; background : skyblue; } .form-parts_item { padding : 10px ; background : orange; } |
こちらも同様に意図したレイアウトにできました。
display: grid;を設定した場合の対応後のデモページ
注意点として、MDNのdisplayのページ内に以下のような記載がありました。
display: contents
一部のブラウザーの現在の実装では、アクセシビリティツリーから
display
の値がcontents
であるすべての要素を削除します (ただし子孫は残ります)。これにより、その要素自身は読み上げソフトでは読み上げられなくなります。これは CSS 仕様書によれば正しくありません。
display: contents; を使用することによりアクセシビリティ上の問題があったようなのですが、引用にもある別の記事によると、2022年5月以降の主要ブラウザでは基本的には解消されているようです。
いくつかのスクリーンリーダーで読み上げを試してみましたが、display: contents; の設定の前と後で特に変化はなさそうでした。
コメントが承認されるまで時間がかかります。