Aplicar estilo a un pseudo- seleccionar manteniendo toda la funcionalidad nativa

Di que necesitas diseñar un select</code> because a designer thought it was a great idea or because a product owner wants a select</code> to looks in a particular way. We all know how difficult it is to have form</code> elements look consistent across browsers or OS's let a alone a select</code>. If you ever ask a developer, how do you style a select</code>? The answer is most likely going to be "you don't".

Entonces, ¿cómo se le da estilo a una selección sin darle estilo? la idea detrás de esta solución es agregar un div absolutamente posicionado detrás delselect</code>, set the opacity to 0 on it, and style the element that was just injected. This way you never lose the functionality of a select and do not have to worry about another element triggering a change</code> event.

HTML

<form>
<fieldset>
<select class="pseudo-me">
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3 - A Longer Option">Really Really Long Option</option>
</select>
</fieldset>
</form>​

CSS

body { margin:2%; }

select.pseudo-me,
.pseudo-select,
.select-container {
top
:0;
left
:0;
}

select.pseudo-me,
.pseudo-select,
.pseudo-select .down-arrow,
.pseudo-select .down-arrow-container {
position
:absolute;
}

.select-container { position: relative; }

select.pseudo-me {
opacity
:0;
z
-index:2;
}

.pseudo-select { z-index:1; }

.pseudo-select .down-arrow-container {
top
:0;
right
:0;
}

.pseudo-select .down-arrow {
display
: block;
border
-style:solid;
}

​

JS (requiere jQuery)

$('select.pseudo-me').each(function() {

var $this = $(this),
BORDER
= ($this.css('border-width') == '' || parseInt($this.css('border-width')) == 0) ? '1px solid #000' : $this.css('border'),
BORDER_COLOR
= ($this.css('border-color') === '') ? '#000' : $this.css('border-color'),
COLOR
= $this.css('color'),
BORDER_RADIUS
= ($this.css('border-radius') == '' || parseInt($this.css('border-radius')) == 0) ? '5px' : $this.css('border-radius');

$this

.wrap('<div class="select-container"></div>')
.after('<div class="pseudo-select"><span class="pseudo-select-text"></span><div class="down-arrow-container"><span class="down-arrow"></span></div></div>')
.on('change', function() {
$
('.pseudo-select-text').text($(this).children('option:selected').text());
});

var $downArrow = $('.down-arrow'),
$downArrowContainer
= $('.down-arrow-container');

$
('.pseudo-select, .select-container')
.width($this.innerWidth())
.height($this.innerHeight());

// the down arrow is calculated as a third of the height of the select
$downArrow

.height($this.innerHeight())
.css({'border-width' : $this.innerHeight() / 3,
'top' : $this.innerHeight() / 3,
'right' : $this.innerHeight() / 6,
'border-color' : BORDER_COLOR + ' transparent transparent'});

// setting the height and width the same so that we have proportional spacing based on the select height.
$downArrowContainer

.height($this.innerHeight())
.width($this.innerHeight())
.css('border-left', BORDER);

$
('.pseudo-select')
.css({'font-family': $this.css('font-family'),
'font-size': $this.css('font-size'),
'padding-left': '5px',
'line-height': $this.innerHeight() + 'px',
'border': BORDER,
'color' : COLOR,
'border-radius' : BORDER_RADIUS });

$
('.pseudo-select-text').text($this.children('option:selected').text());
});​

Un violín que muestra un ejemplo funcional: http://jsfiddle.net/napotopia/gHDvZ/

Este ejemplo hace un poco más que esconde el select</code> and show the faux-select</code> behind it. It gets computed styles and sets default ones when they are not specified. All the styles declared in the CSS portion are for positioning and layout purposes only. Everything that happens on the dynamically generated pseudo-select</code> is either a value retrieved from that element or a calculation most liked based on the border width and border color.

Si cambia el borde, el color o el radio del borde, obtendrá cualquiera de esos valores y actualizará el pseudo-select</code> accordingly: http://jsfiddle.net/napotopia/gHDvZ/186/

También hay que tener en cuenta el hecho de que el borde y el cambio de color en este último ejemplo se están aplicando al select</code> so the hidden element still gets styled as its faux clone.

Realmente no me gusta la idea de toda esta piratería. Mi primera respuesta es siempre no diseñar unselect</code>. Let each device and/or operating system handle how it should look or behave. This hack worked particularly well for a recent hybrid app where a select had to be styled in a specific way but the native functionality was still desired. Use with caution...