Entradas de formulario de estilo personalizado con funciones CSS modernas
Hoy en día, es completamente posible crear casillas de verificación, botones de opción e interruptores personalizados, sin dejar de ser semántico y accesible. ¡Ni siquiera necesitamos una sola línea de JavaScript o elementos HTML adicionales! De hecho, últimamente se ha vuelto más fácil que en el pasado. Vamos a ver.
Aquí es donde terminaremos:
¡Las cosas se han vuelto más fáciles de lo que eran!
La razón es que finalmente podemos aplicar estilo a los pseudoelementos ::before
y en la propia etiqueta. Esto significa que podemos mantener y diseñar un y no necesitaremos ningún elemento adicional. Antes, teníamos que depender de alguien como un extra o un , para realizar un diseño personalizado.::after
input
input
div
span
Miremos el HTML
Nada especial aquí. Podemos diseñar nuestras entradas solo con este HTML:
!-- Checkbox --input type="checkbox"!-- Radio --input type="radio"!-- Switch --input type="checkbox"
Eso es todo por la parte HTML, pero por supuesto se recomienda tener atributos de nombre e identificación, además de un label
elemento coincidente:
!-- Checkbox --input type="checkbox" name="c1"label for="c1"Checkbox/label!-- Radio --input type="radio" name="r1"label for="r1"Radio/label!-- Switch --input type="checkbox" name="s1"label for="s1"Switch/label
Entrando en el estilismo
En primer lugar, verificamos el soporte de appearance: none;
, incluidos sus compañeros con prefijo. La appearance
propiedad es clave porque está diseñada para eliminar el estilo predeterminado de un navegador de un elemento. Si la propiedad no es compatible, los estilos no se aplicarán y se mostrarán los estilos de entrada predeterminados. Eso está perfectamente bien y es un buen ejemplo de mejora progresiva en juego.
@supports(-webkit-appearance: none) or (-moz-appearance: none) { input[type='checkbox'], input[type='radio'] { -webkit-appearance: none; -moz-appearance: none; }}
Tal como está hoy, la apariencia es un borrador de trabajo, pero así es como se ve el soporte:
Estos datos de soporte del navegador son de Caniuse , que tiene más detalles. Un número indica que el navegador admite la función en esa versión y superiores.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
83* | 80 | No | 83* | 15.4 |
Móvil/Tableta
androidcromo | Android Firefox | Androide | Safari en iOS |
---|---|---|---|
125 | 126 | 125 | 15.4 |
Al igual que los enlaces, debemos considerar diferentes estados interactivos con elementos de formulario. Los consideraremos al diseñar nuestros elementos:
:checked
:hover
:focus
:disabled
Por ejemplo, así es como podemos diseñar nuestra entrada de alternancia, crear la perilla y tener en cuenta el :checked
estado:
/* The toggle container */.switch { width: 38px; border-radius: 11px;}/* The toggle knob */.switch::after { left: 2px; top: 2px; border-radius: 50%; width: 15px; height: 15px; background: var(--ab, var(--border)); transform: translateX(var(--x, 0));}/* Change color and position when checked */.switch:checked { --ab: var(--active-inner); --x: 17px;}/* Drop the opacity of the toggle knob when the input is disabled */.switch:disabled:not(:checked)::after { opacity: .6;}
Estamos usando el input
elemento como un contenedor. La perilla dentro de la entrada se crea con el ::after
pseudoelemento. Nuevamente, ¡ya no es necesario realizar un marcado adicional!
Si abre los estilos en la demostración, verá que estamos definiendo algunas propiedades personalizadas de CSS porque se ha convertido en una forma muy agradable de administrar valores reutilizables en una hoja de estilos:
@supports(-webkit-appearance: none) or (-moz-appearance: none) { input[type='checkbox'], input[type='radio'] { --active: #275EFE; --active-inner: #fff; --focus: 2px rgba(39, 94, 254, .25); --border: #BBC1E1; --border-hover: #275EFE; --background: #fff; --disabled: #F6F8FF; --disabled-inner: #E1E6F9; }}
Pero hay otra razón por la que utilizamos propiedades personalizadas: ¡funcionan bien para actualizar valores según el estado del elemento! No entraremos en detalles aquí, pero aquí hay un ejemplo de cómo podemos usar propiedades personalizadas para diferentes estados.
/* Default */input[type='checkbox'],input[type='radio'] { --active: #275EFE; --border: #BBC1E1; border: 1px solid var(--bc, var(--border));}/* Override defaults */input[type='checkbox']:checked,input[type='radio']:checked { --b: var(--active); --bc: var(--active);} /* Apply another border color on hover if not checked not disabled */input[type='checkbox']:not(:checked):not(:disabled):hover,input[type='radio']:not(:checked):not(:disabled):hover { --bc: var(--border-hover);}
Para mayor accesibilidad, debemos agregar un estilo de enfoque personalizado . Estamos eliminando el contorno predeterminado porque no se puede redondear como el resto de las cosas que estamos diseñando. Pero un radio de borde junto con un cuadro de sombra pueden crear un estilo redondeado que funciona como un contorno.
input[type='checkbox'],input[type='radio'] { --focus: 2px rgba(39, 94, 254, .25); outline: none; transition: box-shadow .2s;}input[type='checkbox']:focus,input[type='radio']:focus { box-shadow: 0 0 0 var(--focus);}
También es posible alinear y aplicar estilo al label
elemento que sigue directamente al input
elemento en HTML:
input type="checkbox" name="c1"label for="c1"Checkbox/label
input[type='checkbox'] + label,input[type='radio'] + label { display: inline-block; vertical-align: top; /* Additional styling */}input[type='checkbox']:disabled + label,input[type='radio']:disabled + label { cursor: not-allowed;}
Aquí está esa demostración nuevamente:
Con suerte, estás viendo lo agradable que es crear estilos de formulario personalizados hoy en día. Requiere menos marcado, gracias a los pseudoelementos que se encuentran directamente en las entradas del formulario. Requiere un cambio de estilo menos sofisticado, gracias a las propiedades personalizadas. Y tiene un soporte de navegador bastante bueno, gracias a @supports
.
En definitiva, ¡esta es una experiencia para desarrolladores mucho más placentera que la que hemos tenido que afrontar en el pasado!
Deja un comentario