Durante años, se informó que aplicar diseño a los controles de formulario, como el elemento <select>
, era uno de los principales problemas de los desarrolladores, y hemos estado trabajando en una solución. Si bien este trabajo es complejo y nos llevó mucho tiempo hacerlo bien, estamos muy cerca de lanzar esta función. Una versión personalizable del elemento select se encuentra oficialmente en la etapa 2 en WHATWG, con un gran interés en varios navegadores y un prototipo para que lo pruebes en Chrome Canary 130.
Pruébala y envíanos tus comentarios
Verifica que la instalación de Chrome Canary esté actualizada a la versión 130 y que la marca de funciones experimentales de la plataforma web esté activada. Para activar esta marca, ve a chrome://flags en la barra de direcciones y activa #experimental-web-platform-features. Luego, deberías poder ver las demostraciones de Codepen en esta publicación. Como alternativa, puedes consultar esta colección de Codepen para verlas todas en un solo lugar.
Usa este formulario para enviar comentarios sobre la función. Solo tardará tres minutos en completarse.
Analicemos las funciones de la API de select personalizable, que se basa en la etiqueta select HTML existente.
Habilita la nueva <select>
Para habilitar el nuevo comportamiento, usa la propiedad appearance
de CSS en el botón de selección en la página y en el selector de selección. Para habilitarlo, establece appearance: base-select
en el elemento <select>
y en ::picker(select)
.
::picker(select)
es un nuevo pseudoelemento proporcionado por el usuario-agente que solo se aplica a los elementos <select>
que habilitaron el nuevo comportamiento con appearance: base-select
. Este pseudoelemento del selector es el popover que activa el botón de selección base. Puedes habilitar ambas opciones, como se muestra en el siguiente código:
select,
::picker(select) {
appearance: base-select;
}
Puedes habilitar solo el botón en la página, pero no puedes habilitar solo el pop-up del selector sin habilitar el botón en la página. ::picker(select)
solo se crea una vez que se aplica appearance: base-select
a <select>
.
Ya está todo listo para personalizar tu elemento de selección. El nuevo elemento de selección personalizable incluye algunos estilos predeterminados que se ven igual en todos los navegadores y sistemas operativos. A continuación, se muestra cómo se ve la selección personalizada predeterminada en comparación con la selección existente en Chrome para macOS:
Desglosa las partes
Una vez que estés en el nuevo modo de selección personalizable, los elementos nuevos a los que ahora tienes acceso incluyen los siguientes:
- selectedoption
: Refleja el código HTML interno de la opción que está seleccionada actualmente.
- option::before
: Contiene una marca de verificación para indicar la opción seleccionada actualmente como un indicador de accesibilidad predeterminado (esto está sujeto a cambios).
- ::picker(select)
: Es un cuadro flotante que contiene todo el contenido fuera de button
dentro de una selección personalizable.
Puedes aplicar diseño a cualquier parte del elemento select. Por ejemplo, puedes agregar contenido no interactivo arbitrario dentro de los elementos <option>
, aplicar diseño al botón en la página que abre el menú desplegable de selección y aplicar diseño a la lista desplegable de opciones (el ::picker(select)
).
También puedes aplicar diseño al button
, el indicador de flecha de tu elección, y agregar contenido arbitrario dentro de cualquiera de los elementos y a su alrededor. Además de agregar contenido, puedes ocultar cualquiera de estos elementos nuevos y estilos predeterminados. Por ejemplo, si no quieres que aparezca una marca de verificación de indicador en el pseudoelemento ::before de la opción, usa el siguiente CSS.
/* Remove the default checkmark from the selected option */
option::before {
display: none;
}
Si bien puede haber una cantidad ilimitada de elementos dentro de tu selección, el navegador agrupará todo lo que esté fuera de un elemento <button>
en el pseudoelemento ::picker(select)
, que se comporta como un cuadro flotante anclado al botón. Este <button>
activa o desactiva ::picker(select)
. Las opciones y otros elementos directamente dentro de la selección se elevarán a ::picker(select)
, o bien puedes traer tu propio wrapper para aplicar estilos. Este wrapper también se colocará dentro del pseudoelemento ::picker(select)
.
<select>
<button>
<selectedoption></selectedoption>
</button>
// Everything else that will go into the ::picker(select) popover
</select>
El nuevo <select>
personalizable usa la funcionalidad del popover y el posicionamiento de ancla. Se compila con estas dos tecnologías subyacentes. Esto significa que la lista de opciones desplegables dentro de un elemento select actúa como un popover que está anclado al botón del activador que abre el elemento select.
Puedes usar el posicionamiento de ancla para aplicar diseño a este popover ::picker(select)
(incluso anclarlo a otros elementos). Este modelo de contenido también significa que los estilos de animación de la capa superior funcionan con la lista de opciones para animar los efectos de entrada y salida.
Mejora el elemento <select>
existente
Anteriormente, el equipo de Chrome trabajaba en la idea de un elemento <selectlist>
. En esta publicación, se describe esa función rediseñada para volver a usar el elemento <select>
existente.
Uno de los beneficios clave de la reutilización del elemento <select>
existente es la capacidad de mejorar progresivamente el elemento HTML básico. En comparación con un elemento nuevo, la reutilización de <select>
seguirá renderizando contenido significativo en tu página. En el siguiente ejemplo, se muestra la selección personalizada en comparación con lo que vería un usuario en un navegador no compatible:
Aplica diseño básico
Los cambios pueden ser tan simples como el diseño visual del elemento de selección. Por ejemplo, para actualizar los estilos de los botones, los estilos de desplazamiento y enfoque, o el fondo de las opciones de selección. Después de habilitar appearance: base-select
, aplica el CSS que quieras a las partes de tu selección.
Para personalizar el indicador de flecha, agrega tu propio botón y flecha dentro de la selección.
<select>
<button>
<selectedoption></selectedoption>
<span>
// Arrow here
</span>
</button>
// Everything else that will go into the ::picker(select) popover
</select>
Luego, aplica diseño a la flecha:
/* style the arrow */
button span {
/* arrow styles */
transition: rotate 0.2s;
}
/* adjust arrow styles when the picker is open */
select:open button span {
rotate: -180deg;
}
Contenido complejo dentro de las opciones
Ve más allá con la capacidad de agregar y aplicar diseño a contenido más allá de las cadenas dentro de los elementos <option>
dentro de <select>
. Un ejemplo básico es agregar imágenes de banderas junto a los nombres de los países en un menú desplegable. Para lograrlo, agrega un elemento de imagen junto al texto de la opción.
<option value="france">
<img src="img/flag_of_france.svg" alt="" />
<span>France</span>
</option>
Un ejemplo más complejo podría incluir fotos de perfil, nombres y otra información alternativa para ayudarte a tomar decisiones sobre qué elemento seleccionar en el menú desplegable.
<option value="eur">
<img src="euro-flag.png" alt="" />
<div class="currency">
<div class="currency-short">EUR</div>
<div class="currency-long">Euro</div>
</div>
<div class="symbol" aria-hidden="true">€</div>
</option>
Aplica diseño a la opción seleccionada
Es posible que desees que la opción seleccionada se muestre de forma diferente en el estado seleccionado que en el menú desplegable. Un ejemplo de esto es la IU de Gmail, en la que, para ahorrar espacio, se quita la etiqueta una vez que se selecciona la opción. Para ello, conéctate al elemento <selectedoption>
para aplicarle diseño. <option>
contiene todo el siguiente lenguaje de marcado:
<option value="reply-all">
<img class="material-symbol" src="material-symbol-reply.png">
<span class="text">Reply all</span>
</option>
Ahora aplica display: none
en .text
dentro de <selectedoption>
' para ocultar el contenido de texto y mostrar solo el ícono:
selectedoption .text {
display: none;
}
Opciones interactivas
Con control total sobre el diseño del ::picker(select)
, basa tu trabajo en la demostración anterior para que sea interactivo cuando se coloque el cursor sobre él y se enfoque. En esta demostración, se usa la nueva función calc-size() para animar el ancho del selector de mostrar los íconos a mostrar el ancho completo de las opciones cuando se coloca el cursor sobre ellas o si el elemento de selección tiene una opción con enfoque visible.
/* base styles when picker is open but not interacted with */
::picker(select) {
width: var(--icon-width);
transition: width 0.5s;
}
/* animate the text in on hover & focus */
::picker(select):hover,
select:has(option:focus-visible)::picker(select) {
/* auto width! */
width: calc-size(auto, size + 0.5rem);
}
Limitaciones y notas de accesibilidad
Un gran poder conlleva una gran responsabilidad. Para mantener la accesibilidad, la función tiene algunas limitaciones.
- Además de los elementos
<option>
, aún no se permiten elementos interactivos (enfocados) dentro de<select>
, como botones o cualquier otro elemento. Por ahora, el modelo de contenido propuesto solo permite los elementos<div>
,<span>
,<option>
,<optgroup>
,<img>
,<svg>
y<hr>
. - Los botones divididos se encuentran actualmente en la fase de experimentación mientras trabajamos en una solución accesible.
En el futuro, se espera que el modelo de contenido se expanda para ser más flexible, a medida que se desarrolle la historia de accesibilidad de estas experiencias.
Conclusión
Nos complace ver el progreso de esta función a través de grupos de trabajo y organismos de estándares, y compartir nuestro progreso a medida que compilamos activamente el prototipo y evaluamos la forma de esta función. Si encuentras algo que no funciona como esperas, avísanos.
Mientras esta función aún está en desarrollo, nos encantaría conocer tus comentarios a través de este formulario breve.
Gracias por ayudarnos a asegurarnos de que todo esté bien y facilitar la creación de controles de formulario accesibles y personalizables en la Web.