fieldset要素内のlegendは通常「rendered legend」として扱われ、特別な仕様になる。そのため他の要素と一列に並べたい場合はそこに配慮する必要がある。
rendered legendの仕様
rendered legendの仕様によると、fieldset配下の子要素は以下の条件を満たしているとrendered legendとして扱われる
- 子要素がlegend要素である
- 子要素のfloatがnoneである
- 子要素のpositionがabsoluteまたはfixedではない
たとえば以下のようなHTMLがあった場合、legendはrendered legendとして扱われ、fieldsetのボーダー上に配置される。
<div>
<fieldset>
<legend>レジェンド</legend>
<label><input type="checkbox" />チェックボックス</label>
</fieldset>
</div>
逆に言えば、float:left
やposition:absolute
を使用すればrendered legendとして扱われなくなり、通常の要素と同じように扱うことができる。
また、display: contentsには「特別な要素に対するdisplay:contentsの効果」という付記があり、display: contents
の場合にrendered legendとして扱わないことが書かれている。
float: left
float: left
を設定すると、rendered legendではなくなり他に要素と同じように扱える。
legend { float: left; width: 200px; }
label { overflow: hidden; }
gridやflexレイアウトで制御することもできるけど、今確認したらSafariでは期待通りに動いてくれないよう。
fieldset { display: grid; grid-template-columns: 200px 200px; }
legend { float: left; }
fieldset { display: flex; }
legend { float: left; flex-basis: 200px; }
label { flex-basis: 200px; }
position: absolute
position:absolute
を使ってもrendered legendでなくすことができる。
fieldset { position: relative; }
legend { position: absolute; width: 200px; box-sizing: border-box; }
label { margin-left: 200px; }
display: contents
display: contentsのサポート状況を見るに、button要素に適用すると問題があるようだけど、legendに対しては問題なく利用できそう。IE非対応だけど。
fieldset { display: grid; grid-template-columns: 200px 200px; }
legend { display: contents; }
また「特別な要素に対するdisplay:contentsの効果」によると、fieldsetにdisplay: contents
を設定すると、fieldsetのprincipal boxがなくなり、fieldsetが普通のコンテンツと同じように描画されるようになる。
この場合、legendは変わらずrendered legendとして扱われるけど、fieldsetのボーダー上にrendered legendを配置するという処理はなくなる(boxが存在しないから)。
その上で、fieldsetの親の要素でdisplay: flex
が設定されると、fieldsetの子要素のformatting contextがFlex formatting contextになり、Flex Layoutの仕様に従ってlegendのboxも配置されるということなのかなと思う。ここはよく分かっていない。
div { display: flex }
fieldset { display: contents; }
legend { flex-basis: 200px; }
label { flex-basis: 200px; }
同じように親の要素に対してdisplay: grid
を設定することで、一列に並べることもできる。
div { display: grid; grid-template-columns: 200px 200px; }
fieldset { display: contents; }
というメモ。