HTML Checkboxes and Radio Buttons

Checkboxes and radio buttons are two special types of the <input> element that let users make choices in a form. A checkbox lets a user turn an option on or off independently of other options, while a radio button lets a user pick exactly one option from a group of mutually exclusive choices. Both are everyday building blocks of forms — from “remember me” checkboxes to “choose a shipping method” radio groups — and understanding how the browser groups and submits them is essential to building forms that work correctly.

Overview / How it works

Both checkboxes and radio buttons are created with the same <input> element, distinguished by the type attribute: type="checkbox" or type="radio". Visually, the browser renders each as a small square (checkbox) or circle (radio) that the user can click to toggle. Internally, both are void elements — like other <input> tags, they have no closing tag and no content between tags; all of their behavior is controlled through attributes.

The key difference between the two types is how the browser treats groups of them:

  • Checkboxes are independent. Each checkbox has its own on/off state, and clicking one never affects any other checkbox on the page, even if they share the same name.
  • Radio buttons are mutually exclusive within a group. The browser determines group membership purely by the name attribute: any set of radio inputs that share the same name value are treated as one group, and selecting one automatically deselects every other radio button in that group. Radio buttons with different name values belong to different groups and don’t affect each other.

Whether an input starts out selected is controlled by the boolean checked attribute. Boolean attributes in HTML don’t need a value — simply being present makes them true, so checked, checked="checked", and checked="" all mean the same thing. Omitting the attribute means unchecked.

On submission, only checked checkbox and radio inputs are sent to the server, each as a name=value pair using the input’s value attribute (or the string on if no value is set). Unchecked boxes and unselected radios are not sent at all — there is no “false” value transmitted. This is a common source of confusion for beginners expecting a checkbox to always submit true/false.

Neither input type has visible text of its own. The label text you see next to a checkbox or radio button in a rendered page always comes from a separate <label> element (or surrounding text), not from the input itself.

Syntax

<input type="checkbox" id="subscribe" name="subscribe" value="yes" checked>
<label for="subscribe">Subscribe to newsletter</label>

<input type="radio" id="size-s" name="size" value="small">
<label for="size-s">Small</label>
Attribute Purpose
type Set to checkbox or radio to pick the input style.
name Groups radio buttons together (same name = one group); also used as the submitted field name for checkboxes.
value The data sent to the server when this input is checked and the form is submitted.
checked Boolean attribute; when present, the input starts out selected.
id A unique identifier, used to connect the input to a <label for="...">.
disabled Boolean attribute; greys out the input and prevents interaction and submission.
required For radio groups, requires at least one radio in the group to be selected before the form submits.

Examples

Example 1: A single checkbox

<label for="terms">
  <input type="checkbox" id="terms" name="terms" value="accepted">
  I agree to the terms and conditions
</label>

Result: A single square checkbox appears, followed by the text “I agree to the terms and conditions.” Because the <input> is wrapped inside the <label>, clicking anywhere on the text also toggles the checkbox — not just the tiny box itself.

This pattern (wrapping the input inside the label) is one of two valid ways to associate a label with an input; it removes the need for a separate for/id pair, though many developers use both for clarity and CSS targeting.

Example 2: A group of checkboxes (independent choices)

<fieldset>
  <legend>Choose your toppings</legend>

  <input type="checkbox" id="topping-cheese" name="toppings" value="cheese" checked>
  <label for="topping-cheese">Cheese</label><br>

  <input type="checkbox" id="topping-olives" name="toppings" value="olives">
  <label for="topping-olives">Olives</label><br>

  <input type="checkbox" id="topping-mushroom" name="toppings" value="mushroom">
  <label for="topping-mushroom">Mushroom</label>
</fieldset>

Result: A bordered box (from <fieldset>) with the caption “Choose your toppings” and three checkboxes stacked vertically, each with its own label. “Cheese” appears pre-checked. Note that all three share the name="toppings" attribute, yet checking one does not uncheck the others — unlike radio buttons, checkboxes never suppress each other. Because multiple checkboxes here share one name, a server receiving this form would typically see multiple toppings values, one for each checked box.

Example 3: A group of radio buttons (mutually exclusive choice)

<fieldset>
  <legend>Preferred contact method</legend>

  <input type="radio" id="contact-email" name="contact" value="email" checked>
  <label for="contact-email">Email</label><br>

  <input type="radio" id="contact-phone" name="contact" value="phone">
  <label for="contact-phone">Phone</label><br>

  <input type="radio" id="contact-mail" name="contact" value="mail">
  <label for="contact-mail">Postal mail</label>
</fieldset>

Result: A bordered box titled “Preferred contact method” containing three round radio buttons, with “Email” selected by default. Clicking “Phone” instantly deselects “Email” because both share name="contact"; only one radio button in that group can ever be selected at a time, and only its value is submitted with the form.

How it works step by step

  1. The parser encounters an <input> tag and reads its type attribute to decide whether to render a checkbox or radio control node in the DOM.
  2. For radio inputs, the browser scans the enclosing form (or the whole document if there’s no form) for every other radio input sharing the same name value, forming an implicit group — there is no explicit “group” element or attribute.
  3. When the user clicks a radio button, the browser sets its checked state to true and sets every other radio input in that same group to false, firing change events accordingly.
  4. When the user clicks a checkbox, only that single element’s checked state toggles; no other input is consulted.
  5. On form submission, the browser walks all form controls and includes a name=value pair only for checked checkbox/radio inputs; unchecked ones are omitted entirely from the submitted data.

Common Mistakes

Mistake 1: Giving checkboxes in a group different, unrelated names but expecting radio-like behavior

<input type="radio" name="size-small" value="small"> Small
<input type="radio" name="size-medium" value="medium"> Medium

Because each radio button has a different name, the browser treats them as two separate one-item groups instead of one group of two — both can end up selected at once, defeating the purpose of radio buttons.

<input type="radio" name="size" value="small"> Small
<input type="radio" name="size" value="medium"> Medium

Using the same name for every radio button in the group restores correct mutually-exclusive behavior.

Mistake 2: Relying on the checkbox’s checked attribute for styling text or assuming unchecked values get submitted

<input type="checkbox" name="newsletter"> Subscribe

A developer might expect the server to always receive newsletter=false when unchecked, but nothing is sent at all in that case — the field is simply absent from the submitted data. Server-side code that assumes the key always exists will error or silently misbehave. The corrected approach is to check for the field’s presence rather than assuming a boolean value is always sent, and/or add a hidden fallback field if a default value is required server-side:

<input type="hidden" name="newsletter" value="no">
<input type="checkbox" name="newsletter" value="yes"> Subscribe

Here, if unchecked, the hidden input’s no value is submitted; if checked, both fields submit but most server frameworks take the last value, yes, giving a reliable value either way.

Mistake 3: Forgetting to associate a label, or using invalid nesting

<input type="checkbox" id="opt-in">
<p>Send me updates</p>

The text is a separate, unrelated paragraph — clicking it does nothing, and screen readers won’t announce the checkbox’s purpose. Use an explicit <label for="..."> tied to the input’s id instead:

<input type="checkbox" id="opt-in" name="opt-in" value="yes">
<label for="opt-in">Send me updates</label>

Best Practices

  • Always pair every checkbox and radio button with a <label>, either by wrapping the input or by matching for to the input’s id — this enlarges the clickable target and gives screen reader users a meaningful announcement.
  • Use identical name values for every radio button that should belong to the same mutually-exclusive group, and unique name values (or an array-style name) for independent checkboxes.
  • Group related checkboxes or radio buttons inside a <fieldset> with a descriptive <legend> so the relationship is clear both visually and to assistive technology.
  • Give every option in a group a distinct, meaningful value so the server can tell which option was chosen without guessing.
  • Pre-select a sensible default with checked when one option should usually be chosen, but avoid pre-checking options with legal or financial consequences (like a paid add-on).
  • Remember that styling the actual look of checkboxes/radio buttons (colors, custom shapes) is done with CSS, not HTML attributes — this course covers only the markup and semantics.
  • Use required on at least one radio button in a group when a choice must be made before the form can submit.

Practice Exercises

  1. Build a small survey form with a <fieldset> titled “Favorite season” containing four radio buttons (Spring, Summer, Autumn, Winter) that all share one name, each properly labeled.
  2. Create a “Notification preferences” section with three independent checkboxes (Email, SMS, Push) that a user can check in any combination, and pre-check the Email option by default.
  3. Take the checkbox from exercise 2 and add a hidden input trick so that an unchecked “Email” checkbox still results in a defined value being submitted for that field.

Summary

  • Checkboxes let users pick any number of independent options; radio buttons let users pick exactly one option from a group.
  • Radio button grouping is determined entirely by a shared name attribute — there is no other way to group them.
  • The boolean checked attribute sets the initial selected state; its mere presence means true.
  • Only checked inputs are included in form submission; unchecked ones send nothing at all.
  • Always associate a <label> with each input, and group related options inside a <fieldset> with a <legend> for clarity and accessibility.