La API de selección personalizable ofrece una forma declarativa y basada en CSS de aplicar diseño a los elementos <select> para que coincidan perfectamente con el sistema de diseño de tu marca. Si habilitas appearance: base-select, obtendrás acceso al DOM de sombra interno del elemento select, lo que te permitirá aplicar diseño al botón, a la lista del selector de opciones, al ícono de flecha y al indicador de marca de verificación con propiedades de CSS estándar.
Anteriormente, para lograr un elemento select con un diseño de marca completo, era necesario volver a compilar el control desde cero con JavaScript, lo que a menudo interrumpía la accesibilidad, la navegación con el teclado y la integración nativa de formularios. Con appearance: base-select, obtienes un aspecto personalizado mientras el navegador controla la administración del enfoque, la renderización de la capa superior y las vinculaciones de accesibilidad.
Cómo implementarla
Para implementar el diseño de selección de marca, haz lo siguiente:
- Habilita la personalización: Aplica
appearance: base-selecttanto al elemento<select>como al seudoelemento::picker(select)(que se orienta a la lista desplegable de opciones). - Estructura el botón personalizado (opcional): Define un elemento
<button>directamente dentro de<select>para reemplazar el activador predeterminado. Usa el elemento<selectedcontent>dentro de este botón para representar el texto o el contenido de la opción seleccionada actualmente. - Asigna un estilo a la lista del selector: Usa el pseudoelemento
::picker(select)para aplicar tipografía, colores de fondo, bordes y sombras a la lista desplegable. El navegador renderiza esto en la capa superior, lo que hace que los conflictos dez-indexsean cosa del pasado. - Íconos internos de estilo:
- Usa
select::picker-iconpara aplicar diseño al ícono de flecha o reemplazarlo. - Usa
option::checkmarkpara aplicar diseño al indicador de marca de verificación junto a la opción activa.
- Usa
- Opciones de estilo: Aplica estilos a los elementos
<option>para los estados de desplazamiento, el relleno y el diseño.
Ejemplo de código: Branded Courier Select
En el siguiente ejemplo, se muestra un elemento select personalizado con una fuente monoespaciada y bordes punteados para que coincida con la estética de una marca de "paquetes" específica.
/* Enable customization for the select and its picker */
.brand-select,
.brand-select::picker(select) {
appearance: base-select;
}
/* Style the visible trigger button */
.brand-select {
font-family: 'Courier New', monospace;
background-color: #fffaf0;
color: #8b4513;
border: 2px dashed #8b4513;
border-radius: 4px;
padding: 0.75rem;
font-size: 1rem;
cursor: pointer;
}
/* Style the dropdown options list */
.brand-select::picker(select) {
font-family: 'Courier New', monospace;
background-color: #fffaf0;
border: 2px dashed #8b4513;
border-radius: 4px;
padding: 0.5rem;
}
/* Customize internal part colors to match text */
.brand-select::picker-icon {
color: #8b4513;
}
.brand-select option::checkmark {
color: #8b4513;
}
/* Style individual options and hover effects */
.brand-select option {
padding: 0.5rem;
border-radius: 4px;
color: #8b4513;
cursor: pointer;
}
.brand-select option:hover {
background-color: #fdf5e6;
}
<label for="preferences">Select shipping preference</label>
<select class="brand-select" id="preferences" name="preferences">
<button>
<selectedcontent></selectedcontent>
</button>
<option value="standard">Standard Shipping</option>
<option value="express" selected>Express Shipping</option>
<option value="overnight">Overnight Delivery</option>
</select>
Implementación estratégica y prácticas recomendadas
- SÍ usa
appearance: base-selectcuando tu sistema de diseño requiera una coherencia visual de alta fidelidad en todos los controles de formulario que no se pueda lograr con las anulaciones de selección estándar entre navegadores. - NO uses esta opción si dependes de la experiencia de selector nativo del sistema operativo (p.ej., el selector de rueda del mouse estándar en dispositivos iOS). Si habilitas
base-select, se inhabilitarán los controles de la IU nativa para dispositivos móviles y se usarán los menús de capa superior renderizados en la Web. - SÍ verifica que el contraste de color cumpla con los estándares de las WCAG. El selector personalizable te permite establecer colores ad hoc, pero eres responsable de garantizar que el texto siga siendo legible sobre los fondos personalizados.
- Prueba el comportamiento del diseño. Si configuras
appearance: base-select, se quita el comportamiento predeterminado del navegador de ajustar el tamaño del elemento select en función del ancho de la opción más larga. Es posible que debas establecer un ancho fijo o usar restricciones de flex/grid para evitar cambios en el diseño. - Asegúrate de que tu
<select>tenga un atributonamey un<label>asociado. Esto garantiza que, incluso con una IU personalizada, el componente siga siendo accesible para los lectores de pantalla y funcione correctamente con los envíos de formularios estándar. - Usa atributos
valueestándar en las opciones para asegurarte de que el envío del formulario funcione exactamente como antes.
Estrategias de resguardo
Resguardos y compatibilidad de navegadores para <select> personalizable
En el caso de los navegadores que aún no admiten appearance: base-select, el elemento <select> se degrada de forma elegante a un menú desplegable estándar del sistema operativo.
- Se ignora el contenido que no es de texto: Los navegadores más antiguos quitan las etiquetas HTML (como
<svg>o<div>) dentro de las etiquetas<option>y renderizan solo los nodos de texto. Asegúrate de que el contenido de texto de<option>sea legible y significativo por sí solo. - Manejo de la estructura HTML: Los analizadores estándar pueden ignorar las etiquetas
<button>y<selectedcontent>dentro de<select>o tratarlas como no válidas. No se requieren polyfills de JavaScript pesados para la mejora progresiva si ves el texto estándar como un resguardo legible.
document.addEventListener("DOMContentLoaded", () => {
// Check if browser supports base-select value
if (!CSS.supports("appearance", "base-select")) {
// Custom select overrides are not supported natively.
}
});