Custom radio button using pure CSS (Cross-browser, multiline support)

This demo demonstrates how to create a custom radio button which renders OK on all the browsers. It also supports multiline label text (auto wrap text).

by viphalongpro

HTML

<div>
  <span class='radio'>
    <input type='radio' id='r1'name='radios' checked='true'/>
    <label for='r1'><span></span>
    Can I be wrapped when I grow longer and longer?
    </label>
  </span><br/>
  <span class='radio'>
    <input type='radio' id='r2' name='radios'/>
    <label for='r2'><span></span>Vote me up please :)</label>
  </span>
</div>

CSS

span.radio > input[type='radio'] {
    display:none;    
}
span.radio > label {    
    display:table;     
}
span.radio > label > span {
    display:table-cell;
    width:20px;    
    white-space:nowrap;    
}
span.radio > label > span:before {
    content:'';
    width:20px;
    height:20px;
    border-radius:50%;
    display:inline-block;
    box-shadow: 0 0 4px 2px gray inset;
    vertical-align:middle;       
}
span.radio > label > span:after {
    content:'';
    position:relative;    
    display:inline-block;
    vertical-align:middle; 
    left:-16px;    
    width:12px;
    height:12px;
    border-radius:50%;
    box-shadow:0 0 3px 1px red;
    background:radial-gradient(circle at 2px 2px, white, red);
    visibility:hidden;
}
span.radio > label:hover > span:before {
    box-shadow: 0 0 5px 3px orange inset;
}
span.radio > input[type='radio']:checked + label > span:after {
    visibility:visible;
}
span.radio {    
    display:inline-block;
    margin-bottom:3px;
}

/* This is not part of the custom radio input, it's just a group container to test 
the text wrapping ability of the label text */
div {
    border:1px solid black;
    width:400px;     
    font-size:30px;
    padding:5px;
}

JavaScript

/////Note about the HTML structure, you can only change the label text, radio IDs and radios group name.
/////Each label is treated as a table (CSS table), the inner span is treated as the first column, the inner text of the label is treated as the second column. We hide the real radio and render the fake radio in the first column (using :before for the outer circle and the :after for the inner circle).
/////The interesting thing is we don't need any absolute positioning here except the position:relative for the inner circle. Because the position of the circles depends on the font-size, we need to use white-space:nowrap applied on the span (the first column) to force the 2 circles line up together (also with the effect of vertical-align:middle) , We know the size of the circles so we can set a negative offset left for the inner circle to make it shift left and sit right in the outer circle. This kind of positioning is very interesting indeed.