En este artículo conoceremos los aspectos y características más importantes de las etiquetas html select para personalizar tu menú desplegable con puro CSS.
HTML Select
Entremos directamente en materia. Este elemento HTML con tantos nombres: select, dropdownmenu, combo box, menú desplegable; ha sido mancillado por los frameworks desde hace muchos años con sus versiones no estándares generadas por javascript y aplicando etiquetas aria- para devolverle las funciones de accesibilidad que por defecto tienen la etiqueta <select>
y sus hijos <option>
y <optgroup>
en compañía de sus atributos específicos.
Todo ello con la finalidad de ofrecer versiones estéticamente homogéneas entre los distintos navegadores. Un enfoque que entiendo como diseñador pero que como defensor de los estándares no comparto, al menos en cuanto a la solución se refiere. Si pensamos en un usuario que navega habitualmente desde un navegador concreto, no parece que le vaya a preocupar mucho cómo se vea en el resto, ¿verdad?. Sin embargo, usando estándares, la estética será consistente con cualquier otra página que los use, así como con la ofrecida por el propio sistema operativo, teniendo en cuenta que el drop es un elemento del sistema.
Pero es cierto que a veces esos estilos pueden no pegar mucho con nuestro diseño y ahí sí que me pongo del lado de mi perfil diseñador. Y por ello escribo este artículo: para dar una solución CSS y basada en estándares al diseño de los select.
Pero antes de abordar la cuestión de los estilos, veamos brevemente los elementos que lo componen, así como los principales atributos que luego tomarán protagonismo a la hora de aplicar los CSS.
Elementos html de un menú desplegable
<select> <optgroup> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </optgroup> </select>
Atributos de select
Select soporta los siguientes atributos:
- autocomplete: permite o deniega al navegador sugerir y/o aplicar valores históricos
- autofocus: el select recibe el foco tan pronto se carga la página
- disabled: deshabilita el elemento
- form: conecta el select con form por medio del id de éste sea o no su ancestro.
- multiple: permite la selección de múltiples opciones
- name: es el atributo usado para identificar la información que es enviada por medio del formulario.
- required: hace obligatorio la selección de una opción
- size: permite cambiar el alto en base a líneas de texto, convirtiendo así el dropdown en una lista con scroll en lugar de un desplegable.
Algunos de estos los rescataremos más tarde para ver cómo trasforman su aspecto. Primero vamos a darle unos estilos básicos de partida.
CSS para Select
A primera vista puede parecer que no require gran cosas pero veremos que tiene sus peculiaridades. Comenzamos por lo sencillo y vamos complicando.
* {
/*Para que los bordes y paddings no sumen al width*/
box-sizing: border-box;
} select {
/*Le damos un ancho máximo del menor de los valores 100% y 240px*/
width: min(100%,240px);
/*Padding y line height para lograr la altura deseada, en este caso 48px*/
padding: 12px;
line-height: 24px; /*Un poco de estilo para el borde*/
border: solid 1px #999;
border-radius: 12px;
}
El caret
Esta es la parte clave. Usar una flecha personalizada que indique al usuario que se encuentra ante un menú desplegable y no un simple <input>
.
select {
/*Empezamos eliminando el caret de systema*/
-moz-appearance: none; /*Firefox legacy*/
-webkit-appearance: none; /* Chromes legacy*/
appearance: none;
/*Y a continuación añadimos el nuestro como background*/
background-image: url(/caret.svg);
background-size: 18px;
background-repeat: no-repeat;
background-position: calc(100% - 12px) center; /*Lo posicionamos a la derecha*/
padding-right: 24px; /*le damos algo de espacio para que el caret no se superponga al texto*/
}
:focus y :active
Nos falta un detallito más que es eliminar o personalizar el outline cuando reciba el foco o se active. Podemos definirlo directamente en el selector select
. Y así quedaría con todo junto:
select {
width: min(100%,240px);
padding: 12px;
line-height: 24px;
border: solid 1px #999;
border-radius: 12px;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background-image: url(/caret.svg);
background-size: 18px;
background-repeat: no-repeat;
background-position: calc(100% - 12px) center;
padding-right: 24px;
outline: none;
}
See the Pen
Personalizar Select con CSS by Daniel Abril (@elcssar)
on CodePen.
HTML Optgroup
Optgroup nos permite agrupar las opciones del select y asignar un encabezado al grupo.
Atributos de Optgroup
Para poder asignar dicho encabezado requiere del atributo label.
<optgroup label="Mi encabezado">
<option>Mi opción</option>
</optgroup>
Además soporta el atributo disabled que deshabilitaría todo el grupo de options.
Optgroup – CSS
Optgroup sólo soporta los siguientes atributos de estilo:
- font-family
- font-size
- font-weight. En un optgroup normal equivale a bold. Puedes usar valores numéricos para definir su peso.
- font-style
- color
- background-color
Todos ellos, por defecto, los hereda de select. Por descarte, no soportará line-height, margins o paddings, que son propiedades CSS básicas para adecuar los estilos al diseño.
HTML Option
Seguramente <option>
es la razón por la que has llegado hasta este artículo, buscando la forma de darle estilos después de muchas decepciones. Bien, te reservo una pequeña sorpresa al final del apartado. Pero te pido un poco más de panciencia mientras vemos sus atributos que ocultan detalles interesantes.
Atributos de option
- label. Si lo definimos sobrescribirá el contenido del option
- disabled. Permite deshabilitar un <option> concreto
- selected. Seleccionad un <option> por defecto. Si no lo definimos cogerá el primero de la lista.
- value. Si lo definimos, será el valor que recoja y envíe el formulario; en caso contrario tomará el valor del texto contenido en la etiqueta.
Vamos a usar los atributos disabled y selected para crear una opción no seleccionable a modo de placeholder.
<select> <option selected disabled>--Selecciona una opción--</option> <optgroup> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </optgroup> </select>
Option con CSS
Y llegamos al punto que seguro estabas esperando.
¿Puedo darle estilos a mi option con CSS?
La respuesta es sí.
¿Por qué en todos los foros dicen que no puedo o que están muy limitados?
Bueno, porque de hecho para un <select>
con función de menú desplegable los estilos se limitan a los que hemos visto para <optgroup>
, de quién, por defecto, los hereda.
Pero hay dos formas en que esta limitación puede superarse. La primera cuando usas los atributos multiple o size, como veremos a continuación. La segunda cuando el <option>
pertenece a un <datalist>
. Es decir, cuando el ARIA-role del select deja de ser combobox y pasa a ser listbox.
Multiselect con <select multiple>
El atributo multiple permite que elementos como <select>
o <input>
type file admitan selección múltiples de valores mediante los comandos Ctrl y Shift para añadir valores uno a uno o mediante rangos respectivamente.
Para permitir dicha selección múltiple de opciones del selector, éste crece verticalmente para mostrar todos ellos, perdiendo así su condición de menú desplegable.
El tamaño del select multiple puede ser controlado bien mediante el atributo size, bien mediante CSS. En ambos casos si la altura definida es menor a la de la suma de sus options, aparecerá una barra de scroll.
Atributo size aplicado a select
Este misma transformación podemos lograrla sin necesidad del atributo multiple, simplemente aplicando size, el selector dejará de ser un dropdown menu y nos mostrará la lista scrolleable de options, ésta vez permitiendo sólo la selección simple.
NOTA: como listbox, el scroll del select no puede recibir estilos CSS pero sí mientras conserve su ARIA-role=combobox. Podéis ver cómo en el artículo Personalizar el scroll con CSS.
Estilos CSS ampliados para option
Ésta transformación lleva consigo una ventaja añadida: le confieren a option un mayor número de estilos CSS, entre los que está padding, pero también lo posibilidad de usar pseudoelementos :before y :after. Podéis ver a continuación un ejemplo.
See the Pen
Select size attribute con CSS by Daniel Abril (@elcssar)
on CodePen.
Éstas capacidades fueron las que me llevaron a experimentar para lograr una forma de dar estilos a los option de un select manteniendo la interacción propia de un menú desplegable. Y los resultados de esa experimentación os los brindo en el artículo HTML Option – experimentos CSS. En él se explican más detalles tales como cómo cambiar el horrible fondo azul de la opción seleccionada:
Espero que os haya resultado útil y nos veamos en el próximo. Como siempre, comentarios y preguntas son bienvenidos 😉