acerca de HTML

Referencia de etiquetas

Etiqueta optgroup en HTML: agrupar opciones de select

La etiqueta <optgroup> en HTML agrupa opciones relacionadas dentro de un <select>. Úsala cuando una lista reúne categorías que ayudan a encontrar una opción, como cursos de frontend y backend. Cada grupo tiene un nombre; la persona elige uno de sus cursos, no la categoría completa.

<label for="curso">Curso</label>
<select id="curso" name="curso">
  <optgroup label="Frontend">
    <option value="html">HTML</option>
    <option value="css">CSS</option>
  </optgroup>
</select>

Al abrir la lista, «Frontend» identifica el grupo y HTML o CSS son las opciones seleccionables. Inicialmente se selecciona HTML. Para probar este fragmento en un documento completo, sustituye el formulario del ejemplo práctico por estas líneas.

Sintaxis y contexto válido

En el patrón tradicional, coloca cada <optgroup> directamente dentro de <select> y sus <option> dentro del grupo. Escribe un label descriptivo y utiliza un solo nivel de agrupación: no se pueden anidar grupos. Si necesitas distinguir especialidades dentro de backend, usa nombres como «Backend: bases de datos» y «Backend: servidores» en grupos hermanos.

Los ejemplos muestran </optgroup> explícitamente para que los límites sean claros. El HTML Living Standard permite omitir ese cierre cuando sigue inmediatamente otro <optgroup>, un <hr> o no queda contenido en el padre. No conviertas esa posibilidad en una razón para dejar confusa la estructura.

El selector también puede tener opciones fuera de los grupos. Si solo ofreces dos alternativas sin categorías útiles, basta con <select> y <option>: añadir un grupo no mejora automáticamente la lista.

Label, disabled y valores de selección

Los dos atributos específicos de <optgroup> son:

  • label: nombre visible del grupo. Es obligatorio en el patrón tradicional, sin una leyenda hija. No sustituye al elemento <label> que identifica el selector completo.
  • disabled: atributo booleano que deshabilita las opciones del grupo. Sin él, el grupo no las deshabilita, aunque una opción individual o el selector puedan estar deshabilitados por separado.

La presencia de disabled activa el estado: disabled="false" también deshabilita. Para habilitar el grupo, retira el atributo. MDN describe estos atributos y el agrupamiento tradicional.

¿Se puede seleccionar un <optgroup>? No. El grupo no tiene un value de selección ni aporta un campo propio a los datos del formulario. En el ejemplo, name="curso" pertenece al selector y value="css" a la opción: al elegir CSS, el dato es curso=css, no curso=Frontend.

También admite atributos globales como id, class y lang. font-weight es una propiedad CSS; grupo.disabled y grupo.label son propiedades DOM de JavaScript. Cambiar la tipografía del encabezado no cambia la agrupación.

Ejemplo práctico: cursos por categoría y disponibilidad

Guarda este documento como cursos.html en UTF-8 y ábrelo en el navegador. Tiene dos grupos disponibles y uno temporalmente cerrado. Funciona sin CSS, scripts, archivos adicionales ni servidor. Es una demostración local: no hay botón de envío y las elecciones no se guardan.

<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Elegir un curso</title>
  </head>
  <body>
    <h1>Elegir un curso</h1>
    <form id="optgroup-form">
      <p>
        <label for="optgroup-curso">Curso que quieres estudiar</label>
      </p>
      <p id="optgroup-aviso">
        Elige un curso de Frontend o Backend.
        Próximos cursos todavía no admite inscripciones.
      </p>
      <select id="optgroup-curso" name="curso"
              aria-describedby="optgroup-aviso">
        <optgroup label="Frontend">
          <option value="html" selected>HTML</option>
          <option value="css">CSS</option>
        </optgroup>
        <optgroup label="Backend">
          <option value="php">PHP</option>
          <option value="python">Python</option>
        </optgroup>
        <optgroup label="Próximos cursos" disabled>
          <option value="rust">Rust</option>
          <option value="go">Go</option>
        </optgroup>
      </select>
      <p><button type="reset">Restablecer selección</button></p>
    </form>
  </body>
</html>

Verás HTML seleccionado. Al abrir la lista aparecen Frontend, Backend y Próximos cursos; Rust y Go están deshabilitados. El navegador puede atenuarlos visualmente, pero el aviso visible explica la razón sin depender del color.

  1. Pulsa Tab hasta el selector y utiliza las flechas para recorrer los cursos disponibles. Elige Python; los encabezados y los cursos cerrados no deben convertirse en selecciones. La combinación para abrir y cerrar el desplegable depende del navegador y del sistema.
  2. Pulsa Tab para llegar a «Restablecer selección» y actívalo con Enter o Espacio. Vuelve HTML, porque su opción lleva selected en el documento.
  3. Repite con JavaScript desactivado y en una pantalla estrecha. El agrupamiento, la selección y el restablecimiento son funciones nativas.

Para inspeccionar el valor, vuelve a elegir Python y ejecuta estas líneas en la consola del navegador; no necesitas añadirlas al archivo:

document.getElementById('optgroup-curso').value;
// "python"
new FormData(document.getElementById('optgroup-form')).get('curso');
// "python"

La primera línea lee el valor actual del selector. La segunda construye los datos localmente; no envía una solicitud ni persiste información. Las opciones deshabilitadas no se incluyen como valores enviados. La inspección usa JavaScript, pero la selección del ejemplo sigue funcionando sin él.

Prueba tres cambios en el archivo: cambia label="Backend" por «Programación del servidor» y comprueba que Python conserve value="python"; retira disabled y podrás elegir Rust o Go; finalmente, retira las aperturas y cierres de los grupos conservando las opciones. La lista seguirá funcionando, pero perderá las categorías y los cursos antes agrupados como cerrados quedarán habilitados. Para deshabilitarlos sin el grupo, necesitarías disabled en cada opción.

Accesibilidad y errores frecuentes

Conserva una etiqueta para el selector, nombres breves para los grupos y textos comprensibles para cada opción. La orientación de WAI sobre agrupación de opciones recomienda expresar la relación en el HTML. No añadas roles de menú a un selector nativo.

Con tu lector de pantalla, comprueba que puedas identificar el selector, el grupo y la opción, así como el aviso de disponibilidad. El anuncio exacto varía según navegador, lector y configuración; una presentación en negrita no demuestra por sí sola que esa información se anuncie correctamente.

Si un grupo no aparece o no funciona, revisa su padre <select>, el label, los límites entre grupos y los estados disabled del grupo y del selector. No simules un encabezado con una <option> seleccionable: el lector podría elegirlo y enviarlo como si fuera un curso. Si necesitas jerarquías anidadas, reorganiza las categorías o utiliza varios controles relacionados, por ejemplo con un <fieldset>.

Legend y compatibilidad del select personalizable

El modelo moderno permite una única <legend> como primer elemento hijo de <optgroup>, antes de las opciones. Su texto tiene prioridad sobre label; en ese contexto admite contenido de frase, sin contenido interactivo ni descendientes con tabindex. El estándar define estas restricciones de <legend>.

Este uso pertenece al selector personalizable compatible, cuya presentación se activa con appearance: base-select en el selector y en ::picker(select). No es una técnica para insertar títulos arbitrarios en cualquier desplegable clásico. Conserva un label equivalente como respaldo y prueba el selector completo en los navegadores de tu público. Consulta la guía de <legend> para distinguir este caso de su uso en <fieldset>.

Consulta del 5 de octubre de 2026: MDN clasifica el <optgroup> tradicional como ampliamente disponible. Eso cubre el patrón de los dos ejemplos, no garantiza el contexto nuevo de <legend>.

Chrome ofrece selectores personalizables desde la versión 135, mientras MDN sigue señalando disponibilidad limitada para ese conjunto de funciones. Comprueba por separado la personalización, la leyenda y la alternativa clásica antes de sustituir el patrón tradicional.