Detalles y resumen

Descubre cómo funcionan los detalles y elementos de resumen muy útiles, y dónde usarlos.

Un widget de divulgación es un control de la interfaz de usuario que oculta y muestra contenido. Si lees esto en web.dev y tu viewport tiene menos de 106 ems de ancho, cuando haces clic en el botón "En esta página" que aparece sobre este párrafo, se revela el índice de esta sección. Si no lo ves, reduce el navegador para ver la navegación del índice en esta página como un widget de divulgación.

La interfaz gráfica de usuario de acordeón es una serie de widgets de divulgación que se apilan verticalmente. Un caso de uso común para la IU del acordeón es la página de Preguntas frecuentes en muchos sitios. Las Preguntas frecuentes sobre el acordeón contienen una lista de preguntas visibles; al hacer clic en una pregunta, se expande o "divulga" la respuesta a esa pregunta.

jQuery incluye un patrón de IU de acordeón desde, al menos, 2009. La solución de acordeón original sin JavaScript incluía hacer que cada pregunta de Preguntas frecuentes fuera una <label> seguida de la marca de verificación que etiquetó y, luego, mostrar la respuesta <div> cuando la marca de verificación estaba marcada. El CSS tenía el siguiente aspecto:

#FAQ [type="checkbox"] + div.answer {
  /* all the answer styles */
  display: none;
}
#FAQ [type="checkbox"]:checked + div.answer {
  display: block;
}

¿Por qué la historia? Los widgets de divulgación, como el acordeón, sin JavaScript ni hackeos de controles de formularios, son una adición relativamente reciente. Los elementos <details> y <summary> solo son totalmente compatibles con todos los navegadores modernos desde enero de 2020. Ahora puedes crear widgets de divulgación funcionales, aunque no tan atractivos, con solo HTML semántico. Los elementos <details> y <summary> son todo lo que necesitas: son una forma integrada de controlar la expansión y la contracción del contenido. Cuando un usuario hace clic o presiona una <summary>, o suelta la tecla Intro cuando la <summary> está enfocada, el contenido del <details> superior se muestra visible.

Como todo el contenido semántico, puedes mejorar progresivamente las características y el aspecto predeterminados. En este caso, se agregó una pequeña parte de CSS, pero nada más:

Notarás que estos Codepens no contienen JavaScript.

Activa o desactiva la visibilidad: el atributo open

El elemento <details> es el contenedor del widget de divulgación. <summary> es el resumen o la leyenda de su <details> superior. El resumen siempre se muestra, como un botón que activa o desactiva la visualización del resto del contenido del elemento superior. La interacción con <summary> activa o desactiva la visualización de los elementos del mismo nivel que se etiquetaron automáticamente al activar o desactivar el atributo open del elemento de <details>.

El atributo open es un atributo booleano. Si está presente, independientemente del valor o la falta de este, indica que se muestran todos los contenidos de <details> al usuario. Si el atributo open no está presente, solo se muestra el contenido de <summary>.

Como el atributo open se agrega y se quita automáticamente a medida que el usuario interactúa con el control, se puede usar en CSS para aplicar diseño al elemento de manera diferente según su estado.

Puedes crear un acordeón con una lista de varios elementos <details>, cada uno con un elemento secundario <summary>. Si omites el atributo open en tu código HTML, <details> se contraerá o se cerrará, y solo se verán los encabezados de resumen cuando se cargue la página. Cada encabezado abrirá el resto del contenido del elemento <details> superior. Si incluyes el atributo open en tu código HTML, <details> se renderizará expandido, con el contenido visible, cuando se cargue la página.

El contenido oculto en el estado contraído se puede buscar en algunos navegadores, pero no en otros, aunque no forme parte del DOM. Si realizas una búsqueda en Edge o Chrome, se expandirán los detalles que contengan un término de búsqueda para mostrar el caso. Este comportamiento no se replica en Firefox ni en Safari.

<summary> debe ser el primer elemento secundario de un elemento <details>, que representa un resumen, una leyenda o una leyenda para el resto del contenido del elemento <details> superior en el que se anida. El contenido del elemento <summary> puede ser cualquier contenido de encabezado, texto sin formato o HTML que se pueda usar en un párrafo.

Activa o desactiva el marcador de resumen

En los dos Codepens anteriores, notarás la flecha que se encuentra en el lado de inline-start del resumen. Por lo general, un widget de divulgación se presenta en pantalla mediante un pequeño triángulo que rota (o gira) para indicar el estado abierto o cerrado, con una etiqueta junto a él. El contenido del elemento <summary> etiqueta el widget de divulgación. La flecha que gira en la parte superior de cada sección es un ::marker configurado en el elemento <summary>. Al igual que los elementos de lista, el elemento <summary> admite la propiedad abreviada list-style y sus propiedades de atajo, lo que incluye list-style-type. Puedes cambiar el estilo del triángulo de divulgación con CSS, lo que incluye cambiar el marcador que se usa de un triángulo a cualquier otro tipo de viñeta, incluida una imagen con list-style-image.

Para aplicar otros estilos, usa un selector similar a details summary::marker. El pseudoelemento ::marker solo acepta una cantidad limitada de diseños. Es una práctica común quitar el ::marker y reemplazarlo por el ::before más fácil de diseñar, ya que los estilos de CSS cambian el estilo del contenido generado ligeramente en función de la presencia (o ausencia) del atributo abierto. Para quitar el ícono del widget de divulgación, configura list-style: none o establece el contenido del marcador en none, pero siempre incluye indicadores visuales para informar a los usuarios videntes que el contenido de resumen es un botón de activación que mostrará y ocultará el contenido tras la activación.

details summary::before {
  /* all the styles */
}
details[open] summary::before {
  /* changes applied when open only */
}

En este ejemplo, se quita el marcador predeterminado y se agrega contenido generado para crear un elemento + cuando se cierran los detalles y un objeto - cuando se abren.

Si quieres que el bloque de detalles se abra de forma predeterminada, incluye el atributo open en la etiqueta <details> de apertura. También puedes agregar espacio entre cada diálogo y hacer una transición de la rotación del marcador creado con contenido generado para mejorar el aspecto:

Cómo se manejan los errores

Si no incluyes una <summary>, el navegador creará una para ti, con un marcador y la palabra "detalles". Este resumen forma parte de una shadow root y, por lo tanto, no se aplicarán diseños de resumen de CSS de autor. Lamentablemente, Safari no incluye los detalles en el orden de enfoque del teclado.

Si incluyes un <summary>, pero no es el primer elemento del <details>, el navegador sigue mostrando el resumen como debería. Tampoco fallará si incluyes un vínculo, una etiqueta o algún otro elemento interactivo en el resumen, pero los navegadores manejan el contenido interactivo dentro del contenido de manera diferente. Por ejemplo, si incluyes un vínculo en un resumen, algunos navegadores agregarán el resumen y el vínculo al orden de tabulación predeterminado, pero otros no se enfocarán en el vínculo de forma predeterminada. Si haces clic en un <label> anidado en un <summary>, algunos navegadores enfocarán el control de formulario asociado; otros lo enfocarán en el control de formularios y activarán o desactivarán <details>.

La interfaz de HTMLDetailsElement

Al igual que todos los elementos HTML, HTMLDetailsElement hereda todas las propiedades, los métodos y los eventos de HTMLElement y agrega la propiedad de instancia open y un evento toggle. La propiedad HTMLDetailsElement.open es un valor booleano que refleja el atributo HTML open y que indica si se debe mostrar al usuario el contenido del elemento (sin contar el <summary>). El evento de activación se activa cuando el elemento <details> se abre o se cierra. Puedes escuchar este evento con addEventListener().

Si deseas escribir una secuencia de comandos para cerrar los detalles abiertos cuando el usuario abra cualquier otro detalle, quita el atributo abierto usando removeAttribute("open"):

Este es el único ejemplo en el que se usa JavaScript. Es probable que no necesites JavaScript, excepto para esta funcionalidad de cerrar otros widgets de divulgación abiertos.

Recuerda que <details> y <summary> pueden tener muchos estilos y hasta se pueden usar para crear sugerencias de herramientas. Sin embargo, si vas a usar estos elementos semánticos para casos de uso en los que la semántica nativa no coincide, siempre asegúrate de mantener la accesibilidad. La mayor parte del código HTML es accesible de forma predeterminada. Nuestro trabajo como desarrolladores es garantizar que nuestro contenido se mantenga accesible.

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre detalles y resúmenes.

¿<summary> debe ser el primer elemento secundario de qué elemento?

<p>
Vuelve a intentarlo.
<details>
Correcto.
<fieldset>
Vuelve a intentarlo.