Consider this simple example, where we wish to layout a <legend> and its associated input content side-by-side, with no border, rather than using the default <fieldset> display. First, the markup that works as intended:
fieldset {
border: 0;
display: flex;
}
<form>
<fieldset>
<div>
<legend>Choose your favorite monster</legend>
</div>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Now we think, "Isn't that <div> around the <legend> superfluous?" That is, can't we simply remove it, change the <legend> to display:block, and expect the same behavior?
It turns out we cannot:
fieldset {
border: 0;
display: flex;
}
legend {
display: block;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
It now displays top-to-bottom, rather than side-by-side? But why? And is there a way to make it display side-by-side without the extra <div> around the <legend>?
EDIT:
Please note: I am looking for a solution that allows me to layout the two elements ("legend" and "input content") using flexbox. In particular, floating the <legend> is not a valid solution for my use case.
display: contents might be the best candidate here as it will remove the tag to keep only its content so no more issue with the behavior of <legend> tag. Then the flexbox algorithm will automatically make the text as an anonymous flex item so your legend is a flex item.
The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents ref
fieldset {
border: 0;
display: flex;
}
legend {
display: contents;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Set the legend to float:left.
The rules for fieldset are somewhat "magic", but are described in the HTML5 rendering section.
If the [fieldset] element's box has a child box that matches the conditions in the list below, then the first such child box is the 'fieldset' element's rendered legend:
- The child is a legend element.
- The child's used value of 'float' is 'none'.
- The child's used value of 'position' is not 'absolute' or 'fixed'.
position:absolute and position:fixed causes other issues. But float is perfect, because, since it's a flex item, it won't actually behave like a float, but as a regular flex item. I've added justify-content:space-around to demonstrate that that's actually happening.
fieldset {
border: 0;
display: flex;
justify-content:space-around;
}
legend {
display: block;
float:left;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With