Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=1051d564-713e-4911-93e8-51b518b8544f

HTML: Cómo incluir separadores y grupos en selectores desplegables

Imagen ornamental de portadaLos selectores desplegables de HTML (elementos <select>) son elementos que permiten al usuario elegir una opción entre varias disponibles.

En su estado original son muy prácticos para cuando hay pocos elementos. Sin embargo, por claridad, a veces es necesario agrupar las opciones por categorías o temas, para facilitar la navegación y la selección a los usuarios.

En este artículo vamos a ver cómo incluir separadores en los selectores desplegables de HTML e incluso cómo podemos generar grupos para hacerlo más sencillo.

Separación básica de los elementos en grupos

Los selectores desplegables en formularios con HTML son muy fáciles de crear: basta con usar un elemento <select> con varias opciones <option>, así:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <option value="1">.NET y C#</option>
    <option value="2">Plataforma Java</option>
    <option value="3">JavaScript</option>
    <option value="4">Dart</option>
</select>

Esto se verá de la siguiente manera:

El aspecto del selector desplegable

El problema es que si tenemos muchos elementos, y no solo 3 o 4, se complica la cosa a la hora de leerlos, especialmente si queremos agruparlos de alguna manera:

Aspecto con muchas más opciones: la lista se complica para elegir algo

En el desplegable anterior, con 10 elementos, en realidad tenemos los cursos ordenados por 3 categorías diferentes: lenguajes de programación, áreas de desarrollo Web y herramientas, pero no es evidente. Al no estar ordenados de la manera obvia (por orden alfabético) se resiente la usabilidad (y no digamos si en vez de 10 fuesen 20 o más elementos) .

Una primera aproximación sería la de incluir elementos "separadores" dentro de la lista de opciones, con su valor vacío o con un valor especial y, mediante JavaScript, evitar que se puedan seleccionar, algo así:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <option value="">---------</option>
    <option value="1">.NET y C#</option>
    <option value="2">Plataforma Java</option>
    <option value="3">JavaScript</option>
    <option value="4">Dart</option>
    <option value="">---------</option>
    <option value="5">Front-End</option>
    <option value="6">Back-End</option>
    <option value="7">Full-Stack</option>
    <option value="">---------</option>
    <option value="8">Control de código</option>
    <option value="9">Contenedores con Docker</option>
    <option value="10">SQL Server</option>
</select>

Fíjate en que hemos añadido varios elementos sin atributo value y con guiones para su texto, que se verían así:

Se ven nuevas opciones con guiones, que visualmente separan a los grupos de elementos

Ahora se ven los grupos mucho más claros, de modo que sí podemos adivinar (más o menos) la forma en la que los hemos ordenado y facilitamos la lectura y la selección de los elementos.

Lo malo de esto es que tenemos que ocuparnos de evitar que se elijan los elementos "comodín" que solo están ahí para separar visualmente los grupos, para lo cual ya hay que utilizar JavaScript y validar el formulario para que no pueda enviarse si no se ha elegido un elemento (en el caso de que sea un campo obligatorio, claro).

Una opción que tenemos desde hace poco tiempo (desde la versión 119 de Chrome, en noviembre de 2023) es añadir simplemente separadores (la etiqueta <hr> convencional) en lugar de estos elementos "ficticios", así:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <hr>
    <option value="1">.NET y C#</option>
    <option value="2">Plataforma Java</option>
    <option value="3">JavaScript</option>
    <option value="4">Dart</option>
    <hr>
    <option value="5">Front-End</option>
    <option value="6">Back-End</option>
    <option value="7">Full-Stack</option>
    <hr>
    <option value="8">Control de código</option>
    <option value="9">Contenedores con Docker</option>
    <option value="10">SQL Server</option>
</select>

Esto se verá correctamente en todos los navegadores excepto en Firefox (bueno, e Internet Explorer, pero "eso" ya no existe), donde simplemente no se renderizarán:

Las barras de separación se ven como rayas entre las opciones

Cada sistema operativo las dibuja de forma diferente. En macOS (por cierto, Safari también los soporta), por ejemplo, se ven más separadas de las otras opciones y se aprecian mejor, pero en Windows salen de esta forma, un tanto fea. Que yo sepa no existe modo de controlar su separación de otros elementos usando CSS.

No es una gran opción pero es práctica y nos evita tener que estar validando esos elementos separadores ya que no es posible seleccionarlos.

Agrupación avanzada con "optgroup"

En realidad, existe una manera mucho mejor de separar las opciones en grupos, indicando además de manera explícita cuáles son estos: la etiqueta <optgroup>.

Esta etiqueta es un contenedor de elementos <option> que además permite especificar el título que le queremos dar a cada grupo mediante su atributo label:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <optgroup label="Lenguajes de programación">
        <option value="1">.NET y C#</option>
        <option value="2">Plataforma Java</option>
        <option value="3">JavaScript</option>
        <option value="4">Dart</option>
    </optgroup>
    <optgroup label="Desarrollo Web">
        <option value="5">Front-End</option>
        <option value="6">Back-End</option>
        <option value="7">Full-Stack</option>
    </optgroup>
    <optgroup label="Herramientas">
        <option value="8">Control de código</option>
        <option value="9">Contenedores con Docker</option>
        <option value="10">SQL Server</option>
    </optgroup>
</select>

De esta forma, las opciones se organizan en grupos y se muestran con el encabezado que hayamos indicado, y sangradas en la dirección del texto, dejando mucho más claro todavía a qué se refiere cada conjunto de opciones:

Elementos agrupados de verdad por categorías

Estos elementos no se pueden seleccionar y solamente renderizan los elementos <option> que tengan dentro.

Una excepción son los separadores <hr> que hemos visto antes, que también se renderizan añadiendo una segunda separación dentro del grupo si quisiésemos.

Se pueden anidar, pero el efecto es el mismo que no hacerlo: no se aumenta un nivel en la jerarquía, sino que aparecen como un grupo adicional colocado a continuación del anterior. De hecho, se rompe el grupo anterior si lo incluimos por el medio, por ejemplo:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <optgroup label="Lenguajes de programación">
        <option value="1">.NET y C#</option>
        <option value="2">Plataforma Java</option>
        <optgroup label="Web">
            <option value="3">JavaScript</option>
        </optgroup>
        <option value="4">Dart</option>
        </optgroup>
    </optgroup>
....
</select>

que se vería así:

El grupo se ha roto y no se sangra más el anidado

Fíjate en cómo, en este caso, el elemento "Dart" que pertenece al primer grupo, queda desagrupado y en primer nivel, mientras que el grupo anidado no se sangra para indicar jerarquía respecto al primero, en el que esté contenido.

Es decir, que anidar grupos, aunque posible, no aportada nada y puede ser pernicioso, por lo que es mejor no hacerlo.

Un último detalle sobre estos grupos es que es posible deshabilitarlos para que no puedan ser seleccionados. Esto se consigue mediante el atributo disabled:

<select name="curso">
    <option value="">Elige un tipo de curso</option>
    <optgroup label="Lenguajes de programación" disabled>
        <option value="1">.NET y C#</option>
        <option value="2">Plataforma Java</option>
        <option value="3">JavaScript</option>
        <option value="4">Dart</option>
    </optgroup>
...
</select>

En este caso, al haber deshabilitado el primer grupo, no se puede seleccionar ninguno de sus elementos, y además se muestran en un tono gris apagado para indicar este hecho:

El primer grupo de cursos está deshabilitado no se puede seleccionar, y se ve con un estilo diferente

Es posible cambiarle el estilo a los elementos deshabilitados utilizando la pseudo-clase :disabled, por ejemplo:

optgroup:disabled, optgroup:disabled > option {
    color: #9E9E9E;
    font-style: italic;
}

que los pondría con un color gris ligeramente más claro y en cursiva, para enfatizarlo más. Hay que tener en cuenta que muchas propiedades CSS no tendrán efecto en este caso, ya que no es un elemento renderizado por el navegador, sino un elemento renderizado por el sistema. Por ello, propiedades como border, text-decoration y similares no tendrán efecto alguno y, en general, lo que podremos modificar es más que nada las propiedades relacionadas con la fuente: tipo de letra, color, estilo, tamaño y poco más:

Los deshabilitados en cursiva y un poco más claros

Esta funcionalidad está soportada por todos los navegadores del mercado desde hace décadas pues, a pesar de ser relativamente desconocida, es muy antigua.

¡Espero que te resulte útil!

José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Desarrollo Web

¿Te ha gustado este post?
Pues espera a ver nuestro boletín...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.