Hello all,
When we're creating a webpage, we first put the skeleton of the page with HTML, then add some shiny skin with CSS, and finally add some muscles with JS.
We can add styles (skin) to every HTML element (bones of the skeleton).... except for some form controls. And on this post I'm going to discuss how to sort it out for the radio button.
First let's get to know the radio button. It's an input element with the the type "radio". Usually we add a name attribute so only 1 radio button is checked at any given time, a value attribute to be read by the JS and is usually paired with a label element.
<div>
<input type="radio" name="groupName" value="option1>
<label for="option1">Option 1</label>
</div>
<div>
<input type="radio" name="groupName" value="option2">
<label for="option2">Option 2</label>
</div>And we will get the following output:
Now the styling.
We can't add stylings to the radio buttons and we don't want to create from scratch some new radio buttons (see why at the bottom of the post).
The hacky way forward is:
- to create a new element that we can edit, like a <span>;
- hide the radio button element; and
- wrap everything on the label, so the radio functionality persists and is triggered whenever we click on the label.
So, it will look like this:
HTML<label for="option1" class="container">option1For the CSS, the bulk of the work will be on styling on the checkmark for the different situations, like when it's checked, not checked, and being hovered on:
<input type="radio" name="groupName" id="option1">
<span class="checkmark"></span>
</label>
<label for="option2" class="container">option2
<input type="radio" name="groupName" id="option2">
<span class="checkmark"></span>
</label>/* Customize the label (the container) */This will produce an output like this:
.container {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
user-select: none;
}
/* Hide the browser's default radio button */
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* On mouse-over, add a grey background color */
.container:hover input~.checkmark {
background-color: #bbb;
}
/* When the radio button is checked, add a blue background */
.container input:checked~.checkmark {
background-color: #38f;
}
/* Create a custom radio button */
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 24px;
width: 32px;
background-color: #ccc;
border-radius: 12px;
}
/* Create the indicator (the dot/circle - hidden when not checked) */
.checkmark:after {
display: none;
}
/* Show the indicator (dot/circle) when checked */
.container input:checked~.checkmark:after {
content: "";
position: absolute;
display: block;
}
/* Style the indicator (dot/circle) */
.container .checkmark:after {
top: 8px;
left: 11px;
width: 10px;
height: 8px;
border-radius: 5px;
background: #ddd;
}
It does seem a lot of work (and it is), but it's better than creating a custom component for 2 reasons:
1- It's more accessible. People using a screen reader will more easily understand what's happening, and
2- We don't need to create the JS for this functionality, so less work.
I hope this was helpful and have a great day ;)