Aplicar estilos CSS a campos radio y checkbox
Un problema típico de los formularios es dar estilos personalizados a los elementos input
de tipo radio
y checkbox
. Aunque se les pueden aplicar algunas propiedades de CSS como width, height o box-shadow, lo cierto es que poco más se puede hacer con estos elementos.
Pero ojo, en este artículo no vamos a ver como dar estilos a los propios elementos input
…
Los estilos personalizados se los vamos a dar a los pseudo-elementos :after
y :before
del label
asociado a cada input
, dependiendo de si este tiene la propiedad checked
(si está checkeado) o no.
¿Y por que no damos estilos directamente a los pseudo-elementos de los input
…?
Sería una opción más limpia, pero algunos navegadores (Firefox & Edge) no reconocen los pseudo-elementos :after
y :before
en los input
, así que, tenemos que usar los pseudo-elementos de los label
asociados al input
, de esta manera aprovecharemos la “zona de selección” del label
como podremos ver más adelante.
HTML
La estructura HTML es muy importante, ya que después con CSS podremos dar estilos a los elementos dependiendo de como estén colocados.
Si ponemos el input
y a continuación el label
podemos crear un estilo del tipo input:checked+label
que solo se aplicará cuando el input
esté checkeado.
<input type="checkbox" id="check1" ><label for="check1">Check me!</label>
Con los input
de tipo radio
igual, primero ponemos el input
y después el label
:
<input type="radio" id="radio1"><label for="radio1">Radio 1</label>
<input type="radio" id="radio2"><label for="radio2">Radio 2</label>
Manteniendo esa estructura podemos hacer lo que queramos: flotar elementos, rodearlos con un contenedor, meterlos en una lista, ocultarlos…
CSS
Teniendo en cuenta la anterior estructura HTML para los input
y sus label
podemos crear los siguientes estilos CSS:
input[type="checkbox"] + label {
color: red;
}
Con esta regla de CSS decimos que cualquier label
que esté inmediatamente detrás de un input
de tipo checkbox
tendrá el color del texto rojo.
Pseudo-clase :checked
Y con el selector de la pseudo-clase :checked
podemos modificar los estilos del label
cuando el input
está checkeado. Solo hay que añadir el selector :checked
al input
para, por ejemplo, cambiar el color del texto del label
:
input[type="checkbox"]:checked + label {
color: blue;
}
Con esta regla de CSS decimos que cualquier label
que esté inmediatamente detrás de un input
de tipo checkbox
que esté checkeado tendrá el color del texto azul.
En este punto podemos dar estilos a los label
de los checkbox
checkeados, a sus pseudo-elementos o a cualquier otro elemento que queramos poner dentro o a continuación de los label
como pueden ser span
, img
, etc… mientras se mantengan detrás del input
checkeado.
Hay que tener en cuenta que la idea de usar el label
es por su propiedad de “zona de selección” para el input
. Al asociar los label
a sus input
mediante el atributo for
hacemos que cualquier elemento dentro del label
sea clickable y haga que se marque o se desmarque el checkbox
o el radio
input
asociado a ese label
.
Pseudo-elementos :before
y :after
Con los selectores de los pseudo-elementos :before
y :after
del label
asociado a cada input
podemos crear nuestro checkbox
personalizado. Olvidamos los estilos anteriores y empezamos de cero.
:before
Con el :before
creamos el recuadro del checkbox, primero para cuando no esta checkeado y después añadimos un color de borde diferente para cuando si lo está:
input[type="checkbox"] + label:before {
content: "";
width: 26px;
height: 26px;
float: left;
margin: 0.5em 0.5em 0 0
border: 2px solid #ccc;
background: #fff;
}
input[type="checkbox"]:checked + label:before {
border-color: #0fbf12;
}
:after
Con el :after
creamos la marca del checkbox, pero solo para cuando esté checkeado, lo haremos, como ya hemos visto, con el selector :checked
:
input[type="checkbox"]:checked + label:after {
content: "";
width: 12px;
height: 6px;
border: 4px solid #0fbf12;
float: left;
margin-left: -1.95em;
border-right: 0;
border-top: 0;
margin-top: 1em;
transform: rotate(-55deg);
}
Ajustando la propiedad margin-left
podemos tapar el input
, pero también podemos ocultarlo y no influirá a la hora de checkearlo.
input[type="checkbox"] {
display: none;
}
Solo queda ajustar el texto para que cuadre con el checkbox
, modificar el cursor con la propiedad pointer
y ya que estamos pues creamos dos estilos, sin checkear (gris) y checkeado (verde):
input[type="checkbox"] + label {
font-weight: bold;
line-height: 3em;
color: #ccc;
cursor: pointer;
}
input[type="checkbox"]:checked + label {
color: #0fbf12;
}
Para los input
de tipo radio
sería exactamente igual, lo único que hay que tener en cuenta es que suelen ser redondos…
Esto se soluciona fácilmente añadiendo la propiedad border-radius
al pseudoelemento :before
:
input[type="radio"] + label:before {
content: "";
width: 26px;
height: 26px;
float: left;
margin: 0.5em 0.5em 0 0
border: 2px solid #ccc;
background: #fff;
border-radius: 100%;
}
Y la marca de checkeado también debería ser redonda, por lo que el pseudoelemento :after
quedaría así:
input[type="radio"]:checked + label:after {
content: "";
width: 0;
height: 0;
border: 8px solid #0fbf12;
float: left;
margin-left: -1.8em;
margin-top: 0.8em;
border-radius: 100%;
}
Obviamente podemos añadir estilos para los estados :hover
y :disabled
aunque solo recomiendo el último ya que el :hover
puede resultar confuso. Al checkearlo o des-checkearlo (como el puntero está sobre él) se activa el :hover
y el usuario ya no sabe si está checkeado o no.
Demo
Dejo por aquí una demo donde se incluyen estilos para los input
de tipo radio
y checkbox
. También hay estilos para el estado :disabled
:
En Codepen podéis ver la demo a tamaño completo.
Me ha encantado lo bien que lo explicas todo y que luego vengan los ejemplos visuales, me ha servido para mucho la verdad. Muchas gracias!
Para las etiquetas select y option también se podría hacer? Sobre todo me trae de cabeza el bg azul al clicar sobre la opción. Por si te animas hacer un post de ello, seguro nos ayudas mucho más. Slds
Hola Bea, me alegro de que el artículo te haya servido, esa es la intención. A veces pienso que me excedo explicando algunas cosas, pero lo escribo pensando en como me gustaría encontrarlo a mi.
Para lo del
select
y eloption
que comentas, algo se puede hacer para darles algún estilo con CSS pero está más limitado que en losinput
, ya que ellabel
que usamos con losinput
en elselect
aplica solo alselect
, no a cada uno de losoption
. Y lo del color azul al pasar por encima de cada opción… me suena que solo con CSS no se podía quitar. Seguramente con Javascript se podrá hacer algo más, habrá que investigarlo.Gracias por tu comentario Bea!
Aupa!