Radio Buttons with 2-Way Exclusivity

Avatar of Chris Coyier
Chris Coyier on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

Let’s say you were tasked with creating a UI in which users can rate three candy bars from their most to least favorite. A grid of radio buttons isn’t a terrible way to go about this.

A (small) grid of radio buttons.

The good news is that radio buttons have natural exclusivity in the name-group they are in, and we can use that to our advantage. The bad news is that we have interlocking groups and there is no way to express that in a functional way through HTML alone.

Only one radio button can be selected in each circled group

Let’s craft the HTML in such a way that the horizontal groups share the same name, granting exclusivity automatically. And we’ll also add an HTML data-* attribute which signifies the column which we’ll use to simulate the vertical exclusivity with JavaScript1.

<table>
<tr>
    <th></th>
    <th>1</th>
    <th>2</th>
    <th>3</th>
</tr>
<tr>
    <td>Twix</td>
    <td><input type="radio" name="row-1" data-col="1"></td>
    <td><input type="radio" name="row-1" data-col="2"></td>
    <td><input type="radio" name="row-1" data-col="3"></td>
</tr>
<tr>
    <td>Snickers</td>
    <td><input type="radio" name="row-2" data-col="1"></td>
    <td><input type="radio" name="row-2" data-col="2"></td>
    <td><input type="radio" name="row-2" data-col="3"></td>
</tr>
<tr>
    <td>Butterfingers</td>
    <td><input type="radio" name="row-3" data-col="1"></td>
    <td><input type="radio" name="row-3" data-col="2"></td>
    <td><input type="radio" name="row-3" data-col="3"></td>
</tr>
</table>

Our incredibly simple design can be accomplished with this CSS:

table {
    border-collapse: collapse;    
}
td, th {
    border: 1px solid #ccc;
    padding: 10px;
}
th:empty {
    border: 0;
}

I wouldn’t have even posted that CSS except I think it’s a super useful case of the :empty pseudo class selector.

Now to grant the vertical group exclusivity, we’ll use a touch of jQuery:

var col, el;

$("input[type=radio]").click(function() {
   el = $(this);
   col = el.data("col");
   $("input[data-col=" + col + "]").prop("checked", false);
   el.prop("checked", true);
});

When a radio button is clicked, the column is determined and all other radio buttons in that column are turned off, then the clicked on is turned back on.

That’s all there is to it.

View Demo   Download Files

For the record, I did get this idea from the screencast I linked up earlier in which this idea was briefly mentioned and then discarded.

Also, I’d be interested to hear if people have alternate design pattern ideas for the “rate these three candy bars” thing. That’s always fun to think about.


1 You could, instead, apply the data attributes through JavaScript programatically, or even calculate column on the fly as needed. As ever, there are more ways to kill a cat than choking it with butter.