DEV Community

Cover image for How to Style HTML Radio Buttons: A Step-by-Step Guide
Brian Treese
Brian Treese

Posted on • Edited on • Originally published at briantree.se

How to Style HTML Radio Buttons: A Step-by-Step Guide

HTML radio buttons are a staple of web forms, but their default appearance leaves much to be desired. In this blog post, we'll walk through one of my favorite methods to customize the look of radio buttons using CSS, creating a more user-friendly and visually appealing experience.

Let's Begin by Hiding the Radio Buttons!

We need to start by acknowledging the limitations of cross-browser styling for radio buttons. While it's frustrating that we can't style them directly, we can use workarounds. In this example, the first step is to hide the actual radio button input. I know this sounds odd but we know that we can't style them, so we just need to take them out of the equation. However, this should be done in an accessible manner, ensuring that it remains functional for all users. This can be achieved by using the following set of styles that visually hide the content while retaining its usability:

input[type="radio"] {
  border: 0 !important;
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px !important;
  overflow: hidden;
  padding: 0 !important;
  position: absolute !important;
  width: 1px !important;
}
Enter fullscreen mode Exit fullscreen mode

Creating the Custom Radio Buttons

To create the custom appearance of the radio button, we'll leverage the ::before pseudo-element on our label along with some simple CSS to create the look we're looking for.

For our example, the HTML looks like this:

<form>
    <h1>Can We Style HTML Radio Buttons?</h1>
    <ul>
        <li>
            <input type="radio" value="yes" name="option" id="yes" />
            <label for="yes">Yes</label>
        </li>
        <li>
            <input type="radio" value="no" name="option" id="no" />
            <label for="no">No</label>
        </li>
        <li>
            <input type="radio" value="maybe" name="option" id="maybe" />
            <label for="maybe">Maybe</label>
        </li>
      </ul>
</form>
Enter fullscreen mode Exit fullscreen mode

To start, we'll add the following styles to our label element:

label {
  display: inline-flex;
  align-items: center;
}
Enter fullscreen mode Exit fullscreen mode

This will ensure that once we add our radio button styles it will be properly vertically aligned with the label text.

Now, we'll add our mock radio buttons using the ::before pseudo-element:

label::before {
  content: '';
  display: block;
  height: 1.25em;
  width: 1.25em;
  border: solid 1px #ccc;
  border-radius: 50%;
  margin-right: 0.5em;
}
Enter fullscreen mode Exit fullscreen mode

At this point we have something that is starting to resemble a radio button list but if we click on the radios, we will see that nothing is happening. Although the pseudo-element visually resembles a radio button, it lacks interactivity because we have not yet handled the checked state.

Handling Interaction and States

We can handle the checked state with the :checked pseudo-class and adjacent sibling selector on our label:

input[type="radio"]:checked + label {
  color: black;
}
Enter fullscreen mode Exit fullscreen mode

For the inner dot we can leverage a radial gradient on our pseudo-element:

input[type="radio"]:checked + label::before {
  background: radial-gradient(0.75em circle at center, currentColor 50%, transparent 55%);
  box-shadow: 0 0 1em 0 rgba(10, 150, 255, 0.75);
  border-color: currentColor;
}
Enter fullscreen mode Exit fullscreen mode

There, now when we click on these they function much like native radio buttons. And we can enhance the interactions by adding some transition effects:

label::before {
  ...
  transition: border ease-in 150ms, box-shadow ease-in 150ms;
}
Enter fullscreen mode Exit fullscreen mode

Let's not Forget About Focus

To improve accessibility, we will also need address the focused state of the mock radio buttons. This time we will need to utilize the :focus pseudo-class and the adjacent sibling selector with the label:

input[type="radio"]:checked + label,
input[type="radio"]:focus + label {
  color: black;
}

input[type="radio"]:focus + label::before {
  box-shadow: 0 0 1em 0 rgba(10, 150, 255, 0.75);
  border-color: currentColor;
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

By following this method, we can create stylish and accessible custom radio buttons that greatly enhance the user experience. These customized radio buttons not only look better than the standard ones but can also provide better feedback and interaction when implemented properly.

This was a pretty simple example that may not even really look much different than the native browser styles but the key is, with this set up we can pretty much do whatever we want. So, feel free to experiment with the styles and adapt them to your project's design.

Want to See It in Action?

Check out the demo code and examples of this technique in the in the codepen example below. If you have any questions or thoughts, don't hesitate to leave a comment.

Remember that with a little creativity and some CSS, you can transform the appearance of HTML radio buttons to match your design while maintaining accessibility and usability!

Billboard image

Deploy and scale your apps on AWS and GCP with a world class developer experience

Coherence makes it easy to set up and maintain cloud infrastructure. Harness the extensibility, compliance and cost efficiency of the cloud.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay