formsaccessibility
Don't put links inside a label — the terms and conditions trap
An "I agree to the Terms" checkbox with the link nested inside the label breaks the click target and hides the link behind the control. Move the link out and above. A fieldset is not needed for a single checkbox.
The problem
The consent checkbox is the single most common place this goes wrong:
<form>
<input type="checkbox" id="terms" name="terms" required />
<label for="terms">
I have read and accept the <a href="/terms" target="_blank">terms and conditions</a>.
</label>
<button type="submit">Submit</button>
</form>
It reads fine and it looks fine. Two separate things are broken.
1. The label's surface is no longer one target. Part of it navigates away instead of toggling the box, and nothing tells the user which part is which. Aiming at "terms and conditions" to tick the box leaves the page. MDN is direct about this:
Other than the implicitly associated form control, don't place additional interactive elements such as anchors or buttons inside a
<label>. Doing so makes it difficult for people to activate the form input associated with the label.
2. The link is unreachable until after the commitment. In this markup the checkbox comes before the link in focus order, so a keyboard or screen reader user meets a required "I accept" control before they can reach the terms to read. Melanie Sumner, who tested this markup with a screen reader, also reports a doubled accessible name — "I have read and accept the terms and conditions." announced twice.
The ordering problem is the one that should decide it. Asking for consent before the terms are reachable is a substantive defect, not a technical nitpick.
Try it
Click the words terms and conditions in the first demo, then the label in the second.
Don't — link nested inside the label
Focus order: checkbox → link. The link is reached only after the required control.
Click the link text above.
Do — link outside the label, before the control
Focus order: link → checkbox. Read first, then consent.
Click the link, then the label.
Do
Put the context before the control, so it can be read before the commitment is made:
<p><a href="/terms" target="_blank">Read our Terms and Conditions</a></p>
<label for="terms">
<input id="terms" type="checkbox" name="terms" required />
I agree to the Terms and Conditions
</label>
Don't
<label for="terms">
<input id="terms" type="checkbox" name="terms" required />
I agree to the <a href="/terms">Terms and Conditions</a>
</label>
What about the fieldset and legend version?
Sumner's post ends on a different fix — wrap
the group in a <fieldset> and put the link in the <legend>:
<fieldset>
<legend><a href="/terms" target="_blank">Terms and Conditions</a></legend>
<input type="checkbox" id="terms" name="terms" required />
<label for="terms">I have read and accept the terms and conditions</label>
</fieldset>
We are not adopting this for a single consent checkbox. It solves the ordering problem, but so does moving the link out — without the costs:
<fieldset>means "these controls form a group." One checkbox is not a group. Reaching for it purely to gain somewhere to hang the link inflates the semantics, which undercuts the "semantically accurate" claim made for it.- The legend becomes the group's accessible name, and is commonly announced as context ahead of the control — so the terms text can end up attached to the checkbox announcement anyway, which is close to the doubling the pattern set out to avoid.
- It is the more complicated of two fixes that buy the same thing.
When a fieldset is right: a consent block with several related checkboxes — marketing email, SMS, third-party sharing — is a genuine group and should be marked up as one. The objection is to using a group wrapper for a single control, not to fieldsets.
Why
- Order of operations. Consent should follow the opportunity to read. Any pattern that puts the link after the required control inverts that.
- Two targets, one surface. A nested link carves an unpredictable hole in the label's hit area that nothing communicates visually.
aria-describedbyis not a substitute. Associating the link as help text fixes the click target, but it conveys text without role — the link is not announced as a link, and it still sits after the control.- The rule generalises. Buttons, selects, or a second input inside a label are the same mistake. Only the labelled control belongs in there.
Related
Start with checkboxes need a real label — this pattern assumes the association is already correct.
Sources
- MDN —
<label>: Interactive content - Melanie Sumner — Links in Labels (updated Jun 20, 2022) — the source of the fieldset/legend variant