HTML Guides for checkbox
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The required attribute is a boolean attribute that tells the browser a field must be filled in before the form can be submitted. However, not every input type supports this concept. Some input types always have a value (like range, which defaults to a midpoint, or color, which defaults to #000000), while others represent actions rather than user data (like submit, reset, image, and button). For hidden inputs, the user has no way to interact with the field at all, so requiring them to provide a value makes no sense.
The HTML specification explicitly limits required to the following input types: checkbox, date, datetime-local, email, file, month, number, password, radio, search, tel, text, time, url, and week.
Using required on an unsupported type is invalid HTML. Browsers will typically ignore the attribute in this situation, which means you might believe a field is required when it actually isn't being validated at all. This can lead to forms being submitted with missing or unexpected data. It also creates confusion for assistive technologies — screen readers may announce a field as required even though the browser won't enforce it, misleading users.
How to fix it
- Check the input type. If you're using
requiredon an input with a type likehidden,range,color,submit,reset,image, orbutton, the attribute is not allowed. - Remove the
requiredattribute if the input type inherently provides a value or doesn't accept user-provided data. - Change the input type if you actually need the field to be required and the current type doesn't match your intent.
- Use server-side validation for inputs like
hiddenthat can't userequiredbut still need a value.
Examples
❌ Invalid: required on a hidden input
<form>
<input type="hidden" name="token" required>
<button type="submit">Submit</button>
</form>
The user cannot interact with a hidden input, so required is not allowed here. The browser won't enforce it.
❌ Invalid: required on a range input
<form>
<label for="volume">Volume:</label>
<input type="range" id="volume" name="volume" min="0" max="100" required>
<button type="submit">Submit</button>
</form>
A range input always has a value (it defaults to the midpoint), so required is meaningless and not permitted.
❌ Invalid: required on a color input
<form>
<label for="color">Pick a color:</label>
<input type="color" id="color" name="color" required>
<button type="submit">Submit</button>
</form>
A color input always has a value (defaulting to #000000), so required is not valid here.
✅ Valid: required removed from unsupported types
<form>
<input type="hidden" name="token" value="abc123">
<label for="volume">Volume:</label>
<input type="range" id="volume" name="volume" min="0" max="100">
<button type="submit">Submit</button>
</form>
✅ Valid: required on supported input types
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="dob">Date of birth:</label>
<input type="date" id="dob" name="dob" required>
<label>
<input type="checkbox" name="terms" required>
I agree to the terms
</label>
<button type="submit">Submit</button>
</form>
These input types — email, date, and checkbox — all accept direct user input and are on the allowed list for the required attribute.
An interactive element, like a link, a button or a form field, is nested inside an element whose ARIA role doesn't allow interactive descendants, such as role="tab", role="checkbox" or role="option".
ARIA in HTML gives an element with one of these roles the same content rules as the native control it imitates. A <button> can hold text, but no links, buttons or form fields. An element with role="tab", role="checkbox", role="radio", role="option" or role="menuitem" follows the same rule: phrasing content only, with no interactive content and no elements with a tabindex attribute inside it.
Most of these roles also have presentational children in WAI-ARIA, which means browsers shouldn't expose the element's descendants to assistive technologies. A screen reader can announce the tab and read the link inside it as plain text, with no way to reach it as a link. Keyboard users can also end up with two tab stops for what looks like one control.
The validator checks descendants of elements with role set to button, checkbox, img, link, math, menuitem, menuitemcheckbox, menuitemradio, option, progressbar, radio, separator, slider, switch or tab. It flags <a>, <button>, <details>, <dialog>, <embed>, <iframe>, <label>, <select>, <textarea> and every <input> except type="hidden", plus <audio> and <video> with controls and <img> or <object> with usemap. An <a> is flagged even without href, and one with href gets a second warning, "The element "a" with the attribute "href" should not appear...". Both go away with the same fix.
The validator reports this as a warning because the ARIA in HTML section behind it is non-normative. Older validator builds reported it as an error, with "must not appear" in place of "should not appear".
Keep one interactive element per control. Either put the role on the interactive element itself, as in <button role="tab">, or drop the role and use the native element, like an <input type="checkbox"> with its <label>. If the nested element is a separate action, move it out of the element with the role.
Accordions are a common source of role="tab" warnings. Older Bootstrap accordion examples put role="tab" on each panel heading, with a link inside it that opens the panel. An accordion is not a set of tabs, so remove role="tablist", role="tab" and role="tabpanel", and put a <button> with aria-expanded and aria-controls inside each heading.
Invalid example
<div role="tablist" aria-label="Billing">
<div role="tab" id="tab-monthly" aria-selected="true" aria-controls="panel-monthly">
<a href="#panel-monthly">Monthly</a>
</div>
</div>
<div role="tabpanel" id="panel-monthly" aria-labelledby="tab-monthly">
<p>Billed every month.</p>
</div>
Valid example
<div role="tablist" aria-label="Billing">
<button type="button" role="tab" id="tab-monthly" aria-selected="true" aria-controls="panel-monthly">Monthly</button>
</div>
<div role="tabpanel" id="panel-monthly" aria-labelledby="tab-monthly">
<p>Billed every month.</p>
</div>
Valid example for an accordion
<h2>
<button type="button" aria-expanded="false" aria-controls="answer-shipping">How long does shipping take?</button>
</h2>
<div id="answer-shipping" hidden>
<p>Orders ship within two business days.</p>
</div>
Invalid example with a custom checkbox
<div role="checkbox" aria-checked="false" tabindex="0">
<input type="checkbox" id="newsletter">
<label for="newsletter">Email me the newsletter</label>
</div>
Valid example with a native checkbox
<input type="checkbox" id="newsletter">
<label for="newsletter">Email me the newsletter</label>
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries