Este snippet te permite reemplazar el aburrido checkbox estándar por un moderno toggle switch. Aprovechando los pseudoelementos de CSS y la pseudoclase :checked, conseguimos una animación totalmente fluida sin escribir una sola línea de JavaScript.

Código

<label class="custom-toggle">
  <input type="checkbox" class="custom-toggle-input" aria-label="Toggle Switch" />
  <span class="custom-toggle-slider"></span>
</label>
/* Contenedor del interruptor de palanca */
.custom-toggle {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

/* Ocultar la casilla de verificación predeterminada */
.custom-toggle-input {
  opacity: 0;
  width: 0;
  height: 0;
}

/* Fondo del control deslizante */
.custom-toggle-slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #e2e8f0;
  transition: background-color 0.4s;
  border-radius: 34px;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Perilla del control deslizante */
.custom-toggle-slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

/* Color de fondo al estar marcado */
.custom-toggle-input:checked + .custom-toggle-slider {
  background-color: #3b82f6;
}

/* Contorno en enfoque de teclado */
.custom-toggle-input:focus-visible + .custom-toggle-slider {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

/* Movimiento de la perilla al estar marcado */
.custom-toggle-input:checked + .custom-toggle-slider:before {
  transform: translateX(26px);
}

Puntos de Implementación

El <input type="checkbox"> nativo sufre de inconsistencias visuales entre navegadores y es muy rígido de estilizar. En esta solución, ocultamos visualmente el checkbox real y construimos la interfaz utilizando un elemento <span> adyacente (que actúa como el slider o pista).

  1. Ocultar el input original: Al aplicar opacity: 0, width: 0 y height: 0, el checkbox desaparece visualmente pero conserva toda su semántica y funcionalidad.
  2. Estilo del slider: El “botón” circular del interruptor se renderiza gracias al pseudoelemento ::before.
  3. Animación orgánica: Mediante la propiedad transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55), logramos un easing muy agradable que simula un ligero rebote al accionar el interruptor.
  4. Accesibilidad (a11y): Para garantizar que el estado de foco sea perfectamente visible durante la navegación por teclado, utilizamos :focus-visible para renderizar un contorno de foco (outline) claro.

Este componente es ideal para interfaces que requieren interacciones de encendido/apagado intuitivas, como paneles de configuración o para alternar el modo oscuro.