Guía educativa de customizable select
Personalizar un select sin perder su comportamiento nativo
Aprende qué activa base-select, cómo se conectan botón y picker y qué conserva un formulario cuando la decoración no está disponible.
Modelo mental
El select permite elegir un valor de una lista cerrada. Personalizar su presentación no requiere recrear esa interacción con JavaScript.
<button>Superficie que abre el desplegable.<selectedcontent>Copia del contenido de la opción elegida dentro del botón.::picker-iconIndicador de apertura del select.::picker(select)Superficie que contiene la lista desplegable.<option>Cada elección disponible, con su propio value.::checkmarkMarca de la opción seleccionada dentro de la lista.
appearance: none elimina parte de la apariencia del sistema, pero no habilita por sí solo el picker personalizable. base-select activa otra presentación del control y del desplegable; aplícalo a ambos. El picker pasa a una superficie web en la capa superior, en lugar de la interfaz propia del sistema móvil.
Piensa en dos superficies: el botón muestra la elección actual y el picker contiene las opciones. ::picker-icon señala la apertura; ::checkmark marca la opción seleccionada. Puedes estilizar cada pieza sin sustituir el select por un conjunto de divs.
Mantén un select convencional si sus opciones de texto y la experiencia del sistema ya resuelven la tarea. La personalización resulta útil cuando necesitas controlar la superficie y presentar contenido adicional; no convierte el campo en un buscador ni permite introducir valores libres.
HTML semántico
Empieza por una etiqueta persistente y opciones comprensibles. Este ejemplo permite elegir un método de entrega y no envía ninguna solicitud.
Método de entrega
La etiqueta se asocia mediante for/id. name="delivery" identifica el campo y el value de cada option determina el dato del formulario: al elegir Exprés se obtiene delivery=express, no el texto con el plazo. Traducir la etiqueta no debe cambiar ese contrato.
El primer hijo button contiene selectedcontent, que el navegador rellena con una copia del contenido de la opción elegida. No necesitas sincronizarlo a mano. Si enriqueces las opciones, conserva texto útil, evita IDs que puedan duplicarse al clonar y no introduzcas enlaces o controles interactivos dentro de ellas.
El CSS muestra valores explícitos de color, radio y forma para que puedas reutilizarlo sin los estilos de BaselineLab. light-dark() conserva ambos temas con color-scheme. La preview usa esos mismos valores mediante los tokens del sitio; los controles del playground no modifican el ejemplo.
Estilos y estados
El selector de cada pieza determina dónde actúa la regla. El foco, la apertura y la selección son estados distintos.
select::picker(select)Selecciona el desplegable, no el botón. Activa aquí también appearance: base-select. El navegador lo asocia al select mediante un ancla implícita y lo coloca en la capa superior; no necesitas añadir popover al HTML ni corregir el apilamiento con z-index.
select::picker-iconEstiliza el indicador del botón. Mantener una señal de apertura ayuda a reconocer el campo; el ejemplo cambia su color y conserva su forma nativa.
option:checked / option::checkmarkLa primera regla describe la opción seleccionada; la segunda, su marca. El ejemplo combina peso de texto con el checkmark, para que la elección no dependa solo del color. Hover o foco no significan que el valor ya haya cambiado.
select:open / select:focus-visibleUsa :open para la presentación mientras el picker está abierto y :focus-visible para un contorno de teclado perceptible. No elimines el foco al decorar el borde. Comprueba también las opciones al recorrerlas con flechas.
La receta no necesita animación. Si añades transiciones de entrada y salida, verifica por separado @starting-style, las transiciones discretas y overlay, y respeta prefers-reduced-motion. El soporte del picker no certifica el de esa receta animada.
Soporte y compatibilidad
La mejora debe conservar una elección útil aunque el navegador no represente todas las piezas modernas.
Consulta el valor base-select de appearance y las tablas de selectedcontent, ::picker(select), ::picker-icon y ::checkmark por separado. El estado general de appearance como propiedad no convierte todos sus valores en interoperables.
@supports (appearance: base-select) limita los estilos de mejora a navegadores que aceptan ese valor. Es una consulta de sintaxis, no una prueba de apertura, clonado o accesibilidad. Comprueba el comportamiento completo en los navegadores objetivo. La base no elimina la apariencia convencional y conserva texto legible en todas las opciones.
Referencia convencional explícita
Errores frecuentes
Diagnostica la pieza y el estado antes de añadir más reglas o sustituir el control.
El picker ignora los estilos
- Resultado esperado
- El botón y la lista comparten la presentación personalizada.
- Causa
- Solo se activó base-select en el select, o el navegador no implementa la pieza utilizada.
- Solución
- Actívalo también en ::picker(select); consulta su soporte y prueba apertura y selección reales. No deduzcas soporte completo de CSS.supports().
El contenido seleccionado pierde información
- Resultado esperado
- La elección se entiende tanto en el botón como en la lista.
- Causa
- La información depende de decoración o contenido enriquecido que no se conserva en la presentación convencional.
- Solución
- Incluye un nombre legible en cada option. Usa value estable y selectedcontent para la representación; no uses el texto decorativo como dato del formulario.
Una opción larga desborda
- Resultado esperado
- El texto sigue siendo legible en una pantalla estrecha.
- Causa
- base-select deja de dimensionar el control según la opción más larga. Un ancho intrínseco o nowrap puede forzar desbordamiento.
- Solución
- Define un ancho adaptable para el campo, permite envolver texto y limita el picker al viewport. Prueba todas las elecciones y texto ampliado, no solo la primera.
El control se ve bien pero pierde el foco
- Resultado esperado
- Se puede abrir, recorrer, elegir y cerrar con teclado.
- Causa
- Se quitó outline o se añadió lógica que interfiere con el comportamiento nativo.
- Solución
- Conserva el foco visible. Prueba flechas, selección, Escape y regreso al campo; revisa nombres y anuncios con tecnologías de asistencia en tus entornos objetivo.