Introduction
In the previous chapter, HTML Forms — Labels, we learnt why it's important to label all form controls in HTML, and how exactly to do so using the <label>
element. Labeling controls is clearly a crucial part of building any kind of form in HTML.
However, labeling isn't just limited to individual form controls; sometimes we might well want to label whole groups of form controls that are thematically related in some way.
As a quick example to build the momentum for the rest of this chapter, consider the 'Gender' input example from the previous chapters, illustrated as follows:
Gender
Each radio button represents a choice for the gender input and is labeled by the text next to it.
Most importantly, notice the text 'Gender' at the top here. What does it represent? Well, it technically labels the entire group of the three radio buttons, indicating that they all relate to the 'Gender'.
Previously, we used a mere <p>
element to hold onto this text labeling the group of radios, but in this chapter we shall use features provided by HTML specifically to do so.
We shall look into the <fieldset>
and <legend>
elements.
The <fieldset>
element
The <fieldset>
element is meant to group multiple form controls together into one logical unit, based on the nature of those form controls.
<fieldset>
element is used to group multiple form controls (also known as fields).The nomeclature essentially speaks itself: 'fieldset' means a 'set of fields', where 'field' essentially refers to an input field, a form control. Easy, right?
Quoting from the official HTML standard:
The fieldset
element represents a set of form controls (or other content) grouped together...
Just we like can use a <div>
element to group multiple elements together in the HTML, we can do so using the <fieldset>
element when we're dealing with form controls.
But do keep in mind that <fieldset>
is quite different from the monotonous <div>
— <div>
doesn't convey the semantics of the underlying content, whereas <fieldset>
does. A <fieldset>
element in HTML clearly means that we have a group of related form controls.
In addition to this, compared to a <div>
, a <fieldset>
gets a couple of extra features that help us in working with multiple form controls as a whole, as we shall see in this chapter later on.
name
attribute on a <fieldset>
. However, it isn't used in shaping the form data sent to the server (unlike the case with name
on form controls). name
on <fieldset>
is only used for easy access using JavaScript.Now, <fieldset>
will only take us so far in grouping thematically-related form controls in one place; it won't give a label to the group. For this, we use the <legend>
element.
The <legend>
element
At first glance, the name 'legend' might not self-convey the purpose of the <legend>
element in HTML but it's very easy in theory.
<legend>
element represents a caption for a <fieldset>
element, i.e. a group of related form controls.As per the current specification of the <legend>
element, it is optional to have one in a given <fieldset>
. However, almost always, there is a good reason to have it.
In case we decide to have a <legend>
element, it must be the first element inside <fieldset>
.
Note that <legend>
is a container element. It can contain any valid HTML elements inside it as we shall see in the examples below.
<legend>
element can only go inside a <fieldset>
; it's invalid to have it outside a <fieldset>
.Before we move over to consider some examples, if you're wondering why is <legend>
named so, then the following section is for you.
Why is <legend>
named 'legend'?
Many people might not know of it but, amongst many other definitions, the term 'legend' means caption. And that explains it all.
Examples of <fieldset>
Let's start with improving the radio buttons example presented at the start of this chapter, by incorporating the <fieldset>
element into it.
Here's a review of the code:
<form>
<p>Gender</p>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</form>
First things first, because we know that the radio buttons belong to the same group (for the gender), we nest them inside a <fieldset>
:
<form>
<fieldset>
<p>Gender</p>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</form>
Next up, as there is an obvious label for this group of radios — 'Gender' — albeit in the form of <p>
, we transition it to the <legend>
element which is more appropriate for this job:
<form>
<fieldset>
<legend>Gender</legend>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</form>
And that's it. Let's see the output produced:
Live ExampleSee the visual grouping effect produced by the <fieldset>
element — the entire set of radios reside inside a bordered box, labeled via the <legend>
.
By default, <fieldset>
gets a border style applied to it in addition to a padding. If these out-of-the-box styles don't resonate with us (which is usually the case), we can use some basic CSS to remove them.
In the following code, we remove the border and padding from the <fieldset>
, using the CSS border
and padding
style properties:
<form>
<fieldset style="border: none;padding: 0">
<legend>Gender</legend>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</form>
Perfect!
Disabling <fieldset>
s
As we know from the HTML Forms — Basics chapter, the disabled
attribute can be set on a form control in order to...well...disable it.
If we need to disable two form controls, we need to set disabled
on both of them; disable three form controls, set disabled
on all three of them; and so on.
Fortunately, when we're using a <fieldset>
, we get an advantage. We can disable the <fieldset>
itself in order to get all the form controls that are a part of it to be disabled.
Nice feature, isn't it?
To disable a <fieldset>
, we use its disabled
attribute. It works in the exact same way as the disabled
attribute on a form control.
Consider the following example:
<form>
<fieldset>
<legend>Personal information</legend>
<label>First name <input type="text" name="firstname"></label>
<br>
<label>Last name <input type="text" name="lastname"></label>
<br>
<label>Email <input type="email" name="email"></label>
</fieldset>
</form>
We have three input fields asking for the personal information of a user — his first name, last name, and email address.
If we wish to disable all three of these fields, we can surely go over to each one and disable it manually, as shown below:
<form>
<fieldset>
<legend>Personal information</legend>
<label>First name <input type="text" name="firstname" disabled></label>
<br>
<label>Last name <input type="text" name="lastname" disabled></label>
<br>
<label>Email <input type="email" name="email" disabled></label>
</fieldset>
</form>
However, we can leverage the <fieldset>
element's disabled
attribute to do this at once:
<form>
<fieldset disabled>
<legend>Personal information</legend>
<label>First name <input type="text" name="firstname"></label>
<br>
<label>Last name <input type="text" name="lastname"></label>
<br>
<label>Email <input type="email" name="email"></label>
</fieldset>
</form>
Things to note
<legend>
can only go inside a <fieldset>
A good design decision made by the HTML standard, it's invalid to have the <legend>
element outside of a <fieldset>
.
A <legend>
can go, and only go, inside a <fieldset>
. It doesn't make sense to have <legend>
elsewhere.
Thus, the following is structurally incorrect HTML:
<form>
<legend>Gender</legend> <!-- This can't be here! -->
<fieldset>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</form>
We need to put the <legend>
inside the <fieldset>
so to make the HTML valid:
<form>
<fieldset>
<legend>Gender</legend> <!-- Now, it's correct! -->
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</form>
<legend>
must be the first element inside <fieldset>
Although it's optional to have a <legend>
in a <fieldset>
, when we do have one, it's compulsory to have it at the very beginning of the <fieldset>
.
For example, we can't do the following:
<form>
<fieldset>
<p>Details related to where should we ship your order.</p>
<legend>Shipping information</legend> <!-- This can't come second! -->
...
</fieldset>
</form>
The <legend>
element here is put after a <p>
element inside the <fieldset>
that describes the group.
The correct way is to have the <legend>
right at the beginning, before the <p>
:
<form>
<fieldset>
<legend>Shipping information</legend> <!-- Better now! -->
<p>Details related to where should we ship your order.</p>
...
</fieldset>
</form>
As this example also subtly indicates, it's perfectly valid to have <p>
or any other HTML element inside a <fieldset>
.
<fieldset>
s can be nested in one another
When we're developing complex forms, with complex input requirements, we might find ourselves wanting to have groups of forms controls within groups of form controls.
For example, extending the personal information example in the previous section, suppose we have a group of radios in the <fieldset>
representing the personal information group. As we learnt earlier in this chapter, falling in the same group of inputs, these radios belong to a <fieldset>
of their own — labeled something as 'Gender'.
This suggests that we should have a <fieldset>
containing the gender radio buttons within the <fieldset>
containing all the personal information inputs (including these radios).
The question that stands here is: Can we nest <fieldset>
s within <fieldset>
s?
Turns out, as per the HTML standard, yes we can nest <fieldset>
s within <fieldset>
s.
The following snippet brings the example above into the glyphs of code:
<form>
<fieldset>
<legend>Personal information</legend>
<label>First name <input type="text" name="firstname"></label>
<br>
<label>Last name <input type="text" name="lastname"></label>
<br>
<label>Email <input type="email" name="email"></label>
<br>
<fieldset>
<legend>Gender</legend>
<label><input type="radio" name="gender" value="male"> Male</label>
<label><input type="radio" name="gender" value="female"> Female</label>
<label><input type="radio" name="gender" value="other"> Other</label>
</fieldset>
</fieldset>
</form>
As an extra bit of information, if we set disabled
on the first <fieldset>
(the one corresponding to the personal information group), all the form controls downstream will get disabled, including the radio buttons that sit in another <fieldset>
.
This is demonstrated as follows:
<form>
<fieldset disabled>
<legend>Personal information</legend>
...
</fieldset>
</form>