How to Create Custom Radio Buttons and Checkboxes

Default radio buttons and checkboxes don’t always match your website’s design. In this tutorial, you’ll learn how to fully customize them using HTML, CSS and your own check icon or symbol.

We’ll hide the native input and style the visual version however we like — all accessible and beginner-friendly.


👁️ Preview


🧱 Step 1: Create the Basic HTML Structure

We’ll start with two checkboxes and two radio buttons.

<h2>Custom Checkbox</h2>
<label class="custom-checkbox">
  <input type="checkbox" />
  <span class="checkmark">✔</span>
  Subscribe to newsletter
</label>

<h2>Custom Radio</h2>
<label class="custom-radio">
  <input type="radio" name="plan" />
  <span class="dot">●</span>
  Free Plan
</label>

<label class="custom-radio">
  <input type="radio" name="plan" />
  <span class="dot">●</span>
  Pro Plan
</label>

✅ Explanation

  • We use a <label> so clicking the text also triggers the input.
  • The input is visually hidden but still functional.
  • The span acts as the visual icon (which we can style freely).

🎨 Step 2: Style with CSS to Hide the Default Inputs

input[type="checkbox"],
input[type="radio"] {
  display: none;
}

/* Common label styling */
label {
  display: flex;
  align-items: center;
  margin: 10px 0;
  font-family: Arial, sans-serif;
  cursor: pointer;
}

/* Checkmark box */
.custom-checkbox .checkmark {
  width: 20px;
  height: 20px;
  border: 2px solid #7179F4;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-right: 10px;
  font-size: 14px;
  color: white;
  background-color: transparent;
  transition: all 0.3s ease;
}

/* Dot circle */
.custom-radio .dot {
  width: 20px;
  height: 20px;
  border: 2px solid #7179F4;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-right: 10px;
  font-size: 12px;
  color: white;
  background-color: transparent;
  transition: all 0.3s ease;
}

/* When checked, fill the icon */
input[type="checkbox"]:checked + .checkmark {
  background-color: #7179F4;
}

input[type="radio"]:checked + .dot {
  background-color: #7179F4;
  color: white;
}

🧠 How It Works

  • We hide the real input with display: none.
  • We use the adjacent selector + to apply styles to the custom span when the input is :checked.
  • The content of the span ( or ) can be replaced by any icon, symbol, SVG, or even background image.

🧩 Optional: Use Your Own Icon or Image

Instead of using a text symbol, you can use an image:

<span class="checkmark">
  <img src="check-icon.svg" alt="" />
</span>

And in CSS:

.custom-checkbox .checkmark img {
  width: 16px;
  height: 16px;
}

✅ Final Result

You now have beautiful, accessible, and fully customizable:

  • ✅ Checkboxes
  • ✅ Radio buttons

All styled with your own icons or symbols and responsive to user interaction.


🧩 Bonus Tips

  • Add :focus styles for accessibility.
  • Use aria-checked or proper role="checkbox" if building from scratch (not needed here since we use real inputs).
  • Icons can come from icon libraries like Phosphor, Font Awesome, etc.

Leave a Comment