Usa HTML semántico y accesible con cada casilla de verificación asociada a su etiqueta, ya sea anidando el elemento <input> dentro del elemento <label> o haciendo coincidir el atributo for de la etiqueta con el atributo id de la entrada.
El CSS moderno ofrece dos enfoques para aplicar diseño a las casillas de verificación: personalizar la apariencia nativa con accent-color o anular la presentación predeterminada con appearance: none en el elemento <input type="checkbox">.
Personalización nativa con accent-color
Para un diseño simple y coherente con la marca que conserve la renderización nativa, el comportamiento del teclado, la validación y los indicadores de enfoque del sistema operativo, usa accent-color.
.checkbox-native {
accent-color: #1a73e8;
/* Sizing is controlled via relative units */
inline-size: 1.25em;
aspect-ratio: 1;
margin: 0;
cursor: pointer;
}
Estilo completamente personalizado con appearance: none
Usa appearance: none cuando el diseño requiera control sobre la forma, el tamaño, los estados o los indicadores de la casilla de verificación. Esto quita el diseño visual nativo, pero deja el <input> como el objetivo interactivo.
Establece tamaños relativos explícitos para --checkbox-size y --checkbox-icon-size porque appearance: none quita las dimensiones predeterminadas del navegador. Mantén el ícono más pequeño que la casilla de verificación para dejar espacio para su borde y relleno visual.
/* Reusable SVG assets */
:root {
--icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'></polyline></svg>");
--icon-dash: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='4.5' stroke-linecap='round' stroke-linejoin='round'><line x1='5' y1='12' x2='19' y2='12'></line></svg>");
}
/* Custom checkbox */
.checkbox-custom {
--checkbox-size: 1.25em;
--checkbox-icon-size: 0.7em;
appearance: none;
display: inline-grid;
place-content: center;
inline-size: var(--checkbox-size);
aspect-ratio: 1;
margin: 0;
border: 2px solid currentColor;
cursor: pointer;
&::before {
content: "";
inline-size: var(--checkbox-icon-size);
aspect-ratio: 1;
background-color: currentColor;
mask: var(--checkbox-icon) no-repeat center / contain;
scale: 0;
@media (prefers-reduced-motion: no-preference) {
transition: scale 150ms ease;
}
@media (forced-colors: active) {
background-color: CanvasText;
}
}
&:checked {
--checkbox-icon: var(--icon-check);
}
&:indeterminate {
--checkbox-icon: var(--icon-dash);
}
&:is(:checked, :indeterminate)::before {
scale: 1;
}
&:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
}
El estado indeterminado
El estado indeterminado no se puede establecer a través de un atributo HTML. Establece la propiedad del DOM indeterminate en JavaScript (checkbox.indeterminate = true) y asegúrate de que la pseudoclase :indeterminate sea visualmente distinta de los estados :checked y no marcado:
- Nativo (
accent-color): El navegador aplica el diseño automáticamente con elaccent-colordel elemento (no se necesita una regla de CSS:indeterminateadicional). - Personalizado (
appearance: none): Cambia--checkbox-iconporvar(--icon-dash)en.checkbox-custom:indeterminatecomo se muestra más arriba.
const selectAll = document.querySelector("#select-all");
selectAll.indeterminate = true;
Accesibilidad e interacción
- SÍ uses
:focus-visibleen lugar de:focuspara aplicar diseño a los indicadores de enfoque en las casillas de verificación personalizadas, de modo que aparezca un contorno distinto para la navegación con el teclado sin que se muestre en los clics del puntero. - NO uses
outline: noneni ocultes los indicadores de enfoque en las casillas de verificación. SÍ asegúrate de que la casilla de verificación o su
<label>de unión proporcione un objetivo de hit interactivo de, al menos,44px x 44px, mientras mantienes el tamaño de la casilla de verificación visual en unidades relativas:label { display: inline-flex; align-items: center; gap: 0.65rem; min-block-size: 44px; cursor: pointer; }SÍ proporciona una variante de estilo
:disabledque disminuya la opacidad y establezcacursor: not-allowedpara transmitir claramente los estados inactivos.
Problemas que debes tener en cuenta cuando usas accent-color
La renderización de accent-color en el navegador varía.
En el caso de los indicadores que, por lo general, se pintan sobre un fondo de color de los elementos destacados, como las marcas de las casillas de verificación y los puntos de los botones de selección, los navegadores pueden aplicar diferentes tratamientos:
- Chromium y Firefox suelen seleccionar un color de indicador que contraste.
- En cambio, Safari puede conservar un indicador blanco en el modo claro o un indicador negro en el modo oscuro, mientras modifica el color de los elementos destacados detrás de él. Este ajuste no siempre proporciona suficiente contraste para cada color proporcionado, por lo que debes probar las combinaciones importantes en Safari, incluidos los esquemas de colores claros y oscuros. No asumas que Safari elegirá automáticamente el color del indicador que proporcione el mejor contraste.
Estrategias de resguardo
Resguardos y compatibilidad de navegadores con accent-color
La propiedad accent-color es una mejora progresiva.
Los navegadores que no admitan esta propiedad la ignorarán y usarán los colores predeterminados de su IU.