Select Out of Radio Inputs

How to make a select element out of radio inputs that allow for full custom styling.

by Travis Almand

HTML

<p>Here's an example of a series of radio inputs styled and scripted to behave as a select element. In this way it behaves as a select but every aspect of it can be changed style-wise.</p>

<div class='select-container'>
    <div class='select'>
        <label class='selected'>
            <span>Choose...</span>
        </label>
        <label class='option'>
            <input value='item1' type='radio' name='radios1' />
            <span>Item 1</span>
        </label>
        <label class='option'>
            <input value='item2' type='radio' name='radios1' />
            <span>Item 2</span>
        </label>
        <label class='option'>
            <input value='item3' type='radio' name='radios1' />
            <span>Item 3</span>
        </label>
    </div>
</div>

<p>Here the color scheme is changed with minimal CSS.</p>

<div class='select-container'>
    <div class='select select_alt1'>
        <label class='selected'>
            <span>Choose...</span>
        </label>
        <label class='option'>
            <input value='item1' type='radio' name='radios2' />
            <span>Item 1</span>
        </label>
        <label class='option'>
            <input value='item' type='radio' name='radios2' />
            <span>Item 2</span>
        </label>
        <label class='option'>
            <input value='item3' type='radio' name='radios2' />
            <span>Item 3</span>
        </label>
    </div>
</div>

<p>Here's a more complex alternate style with checkmarks to show the currently selected item.</p>

<div class='select-container'>
    <div class='select select_alt2'>
        <label class='selected'>
            <span>Choose...</span>
        </label>
        <label class='option'>
            <input value='item1' type='radio' name='radios1' />
            <span>Item 1</span>
        </label>
        <label class='option'>
            <input value='item2' type='radio' name='radios1' />
            <span>Item 2</span>
        </label>
       ...

CSS

.select-container {
    height: 40px;
    margin: 10px;
    position: relative;
}
.select {
    background-color: white;
    border: 1px solid rgba(0, 0, 0, 0.5);
    height: 100%;
    overflow: hidden;
    position: absolute;
    transition: all 0.25s;
    width: 100%;
}
.select.open {
    z-index: 100;
}

.option,
.selected {
    cursor: pointer;
    display: block;
    height: 40px;
    line-height: 40px;
    position: relative;
}
.option {
    border-top: 1px solid rgba(0, 0, 0, 0.2);
}
.option:hover {
    background-color: rgba(0, 0, 0, 0.2);
    color: white;
}
.option input {
    left: -100%;
    position: absolute;
}
.option span,
.selected span{
    padding-left: 10px;
}
.selected:after {
    border-left: 10px solid transparent;
	border-right: 10px solid transparent;
	border-top: 10px solid rgba(0, 0, 0, 0.5);
    content: '';
    display: block;
    height: 0; 
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translate3d(0, -50%, 0);
    transform-origin: 0 2px;
    transition: transform 0.25s;
    width: 0;
}
.select.open .selected:after {
    transform: rotate3d(1, 0, 0, 180deg);
}

.checked {
    opacity: 0.25;
}

.select_alt1 {
    background-color: #299A0B;
    color: white;
}
.select_alt1 .selected:after {
    border-top-color: #FFF;
}

.select_alt2 .option span {
    padding-left: 40px;
}
.select_alt2 .option span:before {
    background-image: url(http://www.concretebracknell.co.uk/images/tick.svg);
    background-position: 50%;
    background-repeat: no-repeat;
    background-size: 75%;
    border-radius: 50%;
    content: '';
    display: block;
    height: 40px;
    left: 0;
    opacity: 0.1;
    position: absolute;
    top: 0;
    width: 40px;
}
.select_alt2 input:checked + span:before {
    opacity: 1;
}
.select_alt2 .checked {
    opacity: 1;
}

JavaScript

var $selected = $('.selected');
var $options = $('.option');

$selected.on('click', function () {
    var $this = $(this);
    var $select = $this.parents('.select');
    var height = $select.find('.option').outerHeight() * ($select.find('.option').length + 1);
    
    $select.toggleClass('open');
    
    if ($select.hasClass('open')) {
        $select.css('height', height);
    } else {
        $select.css('height', $select.find('.selected').outerHeight());
    }
});

$options.on('click', function () {
    var $this = $(this);
    var $select = $this.parents('.select');
    
    $select.find('.option span').removeClass('checked');
    $select.find('.selected span').text($this.find('span').text());
    $select.removeClass('open').css('height', $select.find('.selected').outerHeight());
    $this.find('span').addClass('checked');
});