Cross-browser radio buttons and checkboxes using only CSS3

Each browser gives input elements the look and feel it desires, and it cannot be customized directly on every browser. For radio buttons and checkboxes, we can get around this issue by using only CSS3; no need to bring in extra dependencies.

The trick is to use CSS to hide the native input element, and then add an empty span element as the first child of the input's label. Having a label associated to an input allows us to use the CSS3 + syntax to select those specific cases, and then we can select the child empty span to generate our custom look for the input element.

So, if we wanted to customize our radio buttons, first, in HTML, we need to add the dummy span and use labels. For example:

<!doctype html>
<html>
<div>
	<input type="radio" id="radio01" name="radio" />
    <label for="radio01"><span></span>Radio Button 1</label>
</div>
<div>
	<input type="radio" id="radio02" name="radio" />
    <label for="radio02"><span></span>Radio Button 2</label>
</div>
</html>

Notice how each label references an input by its id, using the for attribute. Also, and this is essential, the label's first child element is an empty span. This is what we will use for our CSS:

/* Hide the native radio button */
input[type="radio"] {
    display: none;
}

/* Give format to label text */
input[type="radio"] + label {
    color: orange;
    font-family: Arial, sans-serif;
    font-size: 14px;
}

/* Give format to unchecked radio button by formatting the empty span.
 * Here, we make it black and circular. */
input[type="radio"] + label span {
    background-color: black;
    display: inline-block;
    width: 19px;
    height: 19px;
    margin:-1px 4px 0 0;
    vertical-align: middle;
    cursor:pointer;
    -moz-border-radius: 50%;
    border-radius: 50%;
}

/* When the radio is checked, change just the color
 * (we could add a border, shadow, etc) */
input[type="radio"]:checked + label span{
     background-color: orange;
}

/* Optional: Animations for changing state */
input[type="radio"] + label span,
input[type="radio"]:checked + label span {
  -webkit-transition:background-color 0.4s linear;
  -o-transition:background-color 0.4s linear;
  -moz-transition:background-color 0.4s linear;
  transition:background-color 0.4s linear;
}

Keep in mind that you should avoid adding span elements inside the label; if you do, they will get replaced by the radio button and it will look nasty. If you need to do that, you can use a p (paragraph) with display: inline instead.

This same idea can be used for checkboxes, and other input elements such as select, for a consistent cross-browser look and feel. And using only CSS3, no external framework or library requered.

Inspiration for this post, and live demo to play around. This example uses Compass, but it's not mandatory.

Comments

Popular posts from this blog

VB.NET: Raise base class events from a derived class

Apache Kafka - I - High level architecture and concepts

Upgrading Lodash from 3.x to 4.x