Brian Mwangi

Back to articles

Implement a custom radio input

-- 2 min read

An image of a car radio face

The browser is generous enough to give us default stylings for input elements. However, that styling might be insufficient because we want the inputs to match the theme of our application.

In this article we will learn how to build a custom radio input like the one shown below:

Implementation

We need to be able to select only one choice at a time; therefore we need to use a radio input. Using a radio input instead of a div ensures that we maintain the accessibility features like keyboard navigation. We will then style the radio input to match our desired design.

Let's start by creating a radio input component:

// /components/RadioInput.jsx

function RadioInput() {
  return (
    <label>
      3 hours
          <input
              type="radio"
              name="duration"
              value="3hrs"
            />
    </label>
  );
}

This will render a radio input with the default browser styles

Now let's style the radio inputs to look like what we want. We will be using Tailwind utility classes for our styling. First let's get rid of the default styling by setting " appearance: none" using the appearance-none tailwind utility class.

// /components/RadioInput.jsx

function RadioInput() {
  return (
    <label>
      3 hours
          <input
              type="radio"
              name="duration"
              value="3hrs"
              className="appearance-none"
            />
    </label>
  );
}

After getting rid of the default styling, let's style the <label> to have a gray background and a green outline when active.

// /components/RadioInput.jsx
import { Check } from "/components/Icon";

function RadioInput({ isSelected }) {
  return (
    <label className={`bg-gray-100 py-12 ${isSelected ? 'outline outline-green-500': ''}`}>
          <input
              type="radio"
              name="duration"
              value="3hrs"
              className="appearance-none"
            />
      <div className="absolute inset-0 grid place-items-center">
        <div className="text-center">
            <p className="font-semibold text-xl">3 hours</p>
            <p className="mt-2">Min stake:
              <span className="font-semibold">$ 20</span>
            </p>
        </div>
                {isSelected && <Check className="text-green-500 absolute left-2 bottom-2" />}

            </div>
    </label>
  );
}

The <div> after the <input> contains all the text that we see in the user interface (the duration and minimum stake).

Now we have a custom radio input without sacrificing the accessibility features. That's it 👋🏾. Go and implement accessible custom radio inputs.

WhatsApp icon