Entradas de formulario de estilo personalizado con características CSS modernas | Programar Plus

Es totalmente posible crear casillas de verificación personalizadas, botones de opción e interruptores de palanca en estos días, 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:

¡Seguro que las cosas se han vuelto más fáciles de lo que eran!

La razón es que finalmente podemos diseñar el ::before y ::after pseudo-elementos en el <input> etiquetarse. Esto significa que podemos mantener y diseñar un <input> y no necesitará ningún elemento adicional. Antes, teníamos que depender de un extra <div> o <span>, para realizar un diseño personalizado.

Veamos el HTML

Nada especial aqui. Podemos diseñar nuestras entradas con solo este HTML:

<!-- Checkbox -->
<input type="checkbox">

<!-- Radio -->
<input type="radio">

<!-- Switch -->
<input type="checkbox" class="switch">

Eso es todo para la parte HTML, pero, por supuesto, se recomienda tener atributos de nombre e identificación, además de una coincidencia <label> elemento:

<!-- Checkbox -->
<input type="checkbox" name="c1" id="c1">
<label for="c1">Checkbox</label>

<!-- Radio -->
<input type="radio" name="r1" id="r1">
<label for="r1">Radio</label>

<!-- Switch -->
<input type="checkbox" class="switch" name="s1" id="s1">
<label for="s1">Switch</label>

Entrar en el estilismo

En primer lugar, verificamos el apoyo de appearance: none;, incluidos los complementarios con prefijo. El appearance La 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 funcional, 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 en adelante.

Escritorio

Cromo Firefox ES DECIR Borde Safari
83 * 80 No 83 * TP

Móvil / Tableta

Android Chrome Android Firefox Androide Safari de iOS
96 95 96 15,2 *

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 la :checked Expresar:

/* 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 pseudo-elemento. Una vez más, ¡ya no es necesario 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 buena forma de administrar valores reutilizables en una hoja de estilo:

@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 usamos propiedades personalizadas: ¡funcionan bien para actualizar valores según el estado del elemento! No entraremos en todos los 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 la accesibilidad, deberíamos agregar un estilo de enfoque personalizado. Eliminaremos 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 una sombra de caja 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 diseñar el <label> elemento que sigue directamente el <input> elemento en el HTML:

<input type="checkbox" name="c1" id="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 de nuevo:

Con suerte, está viendo lo bueno que es crear estilos de formulario personalizados en estos días. Requiere menos marcado, gracias a los pseudoelementos que están 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 general, esta es una experiencia de desarrollador mucho más agradable que la que hemos tenido que enfrentar en el pasado.

(Visited 6 times, 1 visits today)