But one thing, the one thing you should never try styling directly is a radio button. Your CSS hubris will tempt you to do so, but trust me: you’re only in for a world of hurt. I know you may have some questions:

Why is this happening?

Because appearance, though it’s a part of Chrome, Safari and Firefox (-webkit-appearance, -moz-appearance), isn’t actually CSS. A lot of people use -webkit-appearance:none to reset the appearance of everything from buttons, inputs, you name it. However, there are a couple of  Firefox bugs that make -moz-appearance:none a dangerous proposition, like playing “the floor is lava” on pogo sticks.

What do you mean I can’t style radio buttons?

I said you shouldn’t try styling them directly. Since appearance does not work completely on both checkboxes and radio buttons. You can still style radio buttons, you’re just going to have to use a bit of trickery in order to pull it off. Here’s how you’d do it.

Check out this Pen!
  1. Set the radio input to display: none.
  2. Style a span adjacent to the radio button the way you’d like to style the radio button.
  3. Toggle its appearance using the :checked attribute.

Browser Support for Radio Button Styles

The graveyard versions of Internet Explorer (8,7,6, etc) do not support :checked. If you need to support them, I’d suggest using this jQuery snippet as well:

And of course, if you have custom checkboxes as well, this same technique will work for them as well.

Part 2: Select Boxes

Select boxes are a lot like radio buttons, due to this bug that prevents you from removing the arrow with appearance, but have courage! It can be removed with a bit of clever CSS. The best way to give a select box a custom arrow is by using a CSS triangle, but select boxes don’t support pseudo-elements. So we’d wrap the select in a paragraph instead, and put the arrow on that:

Check out this Pen!

The browser support for this is almost as good: IE10+. For IE8-9, you can’t remove the select arrow, but you can hide it by changing the padding around until the arrow is behind the pseudo-elements from the paragraph.