Solicitud de comentarios del desarrollador: selección personalizable

Durante años, el diseño de controles de formulario, como el elemento <select>, se ha informado como uno de los principales problemas de los desarrolladores, y estamos 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 seleccionado se encuentra oficialmente en la etapa 2 de WhatWG, con un gran interés en varios navegadores y un prototipo para que pruebes de Chrome Canary 130.

Pruébala y envíanos tus comentarios

Comprueba que la instalación de Chrome Canary se haya actualizado a la versión 130 y que tengas activada la función experimental de funciones de la plataforma web. 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. También 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 versión de <select>

Para habilitar el nuevo comportamiento, usa la propiedad appearance de CSS, tanto en el botón de selección de anuncios in-page como 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 un usuario-agente que solo se aplica a los elementos <select> que se habilitaron para el comportamiento nuevo usando appearance: base-select. Este seudoelemento selector es la ventana emergente que se activa mediante 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 elegir habilitar solo el botón de anuncio in-page, pero no el botón emergente del selector sin habilitar el botón de anuncio in-page. ::picker(select) solo se crea una vez que se aplica appearance: base-select a <select>.

Ya tienes todo listo para personalizar el 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 frente a la selección existente de Chrome en macOS:

Estilo de usuario-agente predeterminado para la selección personalizable de la derecha. Esto está sujeto a cambios, y nos encantaría recibir tus comentarios al respecto.
Demostración de una selección básica en comparación con una selección personalizable.

Desglosar las partes

Diagrama en el que se muestran las partes de una selección.

Una vez que estés en el nuevo modo de selección personalizable, ahora tendrás acceso a los elementos nuevos: - selectedoption: Refleja el 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 de la selección. Por ejemplo, puedes agregar contenido arbitrario no interactivo dentro de los elementos <option>, aplicar diseño al botón de anuncio in-page que abre el menú desplegable de selección y modificar el estilo de la lista desplegable de opciones (la ::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 popover 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 creó con estas dos tecnologías subyacentes. Esto significa que la lista de opciones desplegables dentro de una selección actúa como una ventana emergente anclada al botón de activación que abre la selección.

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 estaba trabajando 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. A diferencia de un elemento completamente 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:

Todo el contenido de texto de option se renderiza en la versión de resguardo del elemento de selección.

Aplica diseño básico

Los cambios pueden ser tan simples como aplicar un diseño visual al 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.

Cambiar los estilos de varias partes de la selección, con el botón predeterminado.

Para personalizar el indicador de flecha, agrega tus propios 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, define el estilo de 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

Llega más lejos con la capacidad de agregar contenido y darle estilo 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>
Selector de países con banderas.

Un ejemplo más complejo podría incluir fotos de perfil, nombres e 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>
Captura de pantalla del selector de moneda.

Aplica diseño a la opción seleccionada

Es posible que quieras que la opción seleccionada se muestre de manera diferente en el estado seleccionado y en el menú desplegable. Un ejemplo de esto es la IU de Gmail, en la que, para ahorrar espacio, la etiqueta se quita 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;
}
Selección de estilo de Gmail con un ícono que representa la opción seleccionada.

Opciones interactivas

Con control total sobre el diseño del ::picker(select), haz uso de la demo 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 el elemento o si la selección tiene una opción con el foco 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);
}
Selección interactiva al estilo de Gmail con contenido que se muestra de forma progresiva cuando se coloca el cursor sobre él o se enfoca.

Limitaciones y notas de accesibilidad

Un gran poder conlleva una gran responsabilidad. Para mantener la accesibilidad, la función tiene algunas limitaciones.

  • Aparte de los elementos <option>, aún no se permiten elementos interactivos (enfocables) dentro de <select>, como botones y otros elementos. Por ahora, el modelo de contenido propuesto solo permite los elementos <div>, <span>, <option>, <optgroup>, <img>, <svg> y <hr>.
  • Los botones de división se encuentran actualmente en la fase de experimentación mientras buscamos una solución accesible.

En el futuro, se espera que el modelo de contenido sea más flexible, a medida que se desarrolla la historia sobre la accesibilidad de estas experiencias.

Conclusión

Nos entusiasma ver el progreso de esta función a través de grupos de trabajo y cuerpos de estándares, y compartimos nuestro progreso a medida que construimos activamente el prototipo y evaluamos la forma de esta función. Si encuentras algo que no funciona como esperabas, avísanos.

Aunque esta función todavía está en desarrollo, nos gustaría recibir tus comentarios a través de este breve formulario.

Gracias por ayudarnos a asegurarnos de hacerlo bien y facilitar la creación de controles de formularios accesibles y personalizables en la Web.