soy Kseso y esto EsCSS

Elementos Details y Summary: toggle nativo de Html5 y CSS para su control

Los nuevos elementos de HTML5 DETAILS y SUMMARY a fondo. Sus particularidades de funcionamiento y los secretos para aplicarles estilos CSS.

Elementos Details y Summary: toggle nativo de Html5 y CSS para su control

·Por Kseso ✎ 6
Elementos Details y Summary: función toggle nativa de Html5

Artículo publicado originalmente en Enero de 2016. Actualizado en Febrero de 2018 con información actual y demos.

ÍNDICE DE CONTENIDO
  1. Marcado html
  2. Soporte navegadores
  3. Details en Details
  4. CSS general
  5. CSS desplegado
  6. Animación apertura y cierre
  7. Todo Junto en una demo
  8. Alterando el despliegue
  9. Enlaces de interés

HTML5 vino, bueno, está en camino, con multitud de elementos que facilitan la interacción del usuario con los contenidos de la página. Y además lo hace de forma nativa y sencilla: el desarrollador sólo tiene que añadir esos elementos y es el navegador quien implementa los recursos necesarios para su correcto funcionamiento.

Uno de estos nuevos elementos interactivos es details y su hijo summary

Básicamente lo que hace es lo mismo que la función toggle: el elemento details de entrada oculta todo su contenido excepto lo incluido en summary y sólo cuando el usuario clica sobre éste último los muestra. El índice de contenidos de este artículo está construido en base a estos elementos.

Podríamos decir que su comportamiento es el del típico elemento que por defecto se muestra colapsado y sólo a demanda del visitante se expande para mostrar su contenido. Como el ejemplo siguiente

Marcado html de Details y Summary

Click para expandir o colapsar Este texto se muestra o se esconde al pinchar en la leyenda anterior.

Su marcado inicialmente es sencillo:

<details> <summary>Click para expandir o colapsar</summary> Este texto se muestra o se esconde al pinchar en la leyenda anterior. </details>

Soporte de navegadores a Details y Summary

Puedes consultar la página caniuse.com para estar al tanto de los navegadores y sus versiones que ya implementan en su núcleo soporte nativo a a los elementos details y summary

Hoy [09/2017] sólo los los IE´s/Edge y Opera Mini no lo hacen.
Firefox, Chrome, Safari y Opera sí, al igual que el navegador de Android.

Details en Details

El ejemplo anterior del marcado html de details es el mínimo funcional. Pero nada impide añadir elementos dentro de details:

<details> <summary>Listado</summary> <dl> <dt>Uno</dt> <dd>Definición de Uno</dd> <dt>Dos</dt> <dd>Definición de Dos</dd> </dl> </details>

¿Te suena? Cambia la lista de definición (dl) por una lista desordenada (ul) y tienes el típico menú desplegable de un sólo nivel en el que nos ahorramos todo lo necesario para mostrar y ocultar las opciones.

Pero este marcado se puede llevar un paso más allá porque el elemento details admite como hijos otros elementos details. Sólo se precisa que cada uno cuente con su correspondiente summary para hacerlo funcional:

See the Pen BjWVvJ by Kseso (@Kseso) on CodePen.

El elemento summary también admite otros elementos dentro de él.

<details> <summary> <label for='nombre'>Texto</label> </summary> <!-- otro contenido --> </details>

Estilos CSS al elemento details y summary

Habrás visto que no he añadido ningún estilo CSS a los ejemplos mostrados hasta ahora. Todo lo relativo a su funcionamiento lo pone el navegador. Eso y unos estilos por defecto como a cualquier otro elemento.

Para darle la apariencia sólo tienes que usar su nombre como selector CSS:

details { /*estilos muy chu-chu-chulos*/ } summary { /*estilos muy chu-chu-chulos*/ }

Estilos CSS para details desplegado

Es posible aplicar reglas específicas para cuando el elemento details se muestra desplegado tras pinchar en su summary correspondiente.

Para ello nos servimos de una particularidad que ocurre al clicar el summary (como con otros elementos como los radio).

Al pinchar en el elemento summary hijo de cada details padre el navegador añade a éste último (el details padre) el atributo open sin valor (no añade ni el signo igual = ni cadena textual tras él entre comillas).

elemento details con atributo open tras pinchar su summary
Elemento details con atributo open tras pinchar su summary

Y aquí viene de perlas un viejo conocido: el selector CSS por nombre de atributo HTML:

details[open] { /* estilos muy chu-chu-chulos para el elemento details en su estado desplegado */ } details[open] > summary { /*estilos muy chu-chu-chulos para el elemento summary en su details padre desplegado */ }

Y como es lógico, el selector CSS details[open] lo podemos usar para afectar a cualquier elemento contenido en él cuando se despliega y muestra.

Actualización Febrero 2016
Hay un hilo en discusión en la lista de Correos del W3c al respecto: la propuesta es que a details y/o summary le sean de aplicación las particularidades de los ítems de lista (display: list-item) y por lo tanto también sea efectivo el pseudoelemento ::marker en ellos.

En teoría el navegador añade al elemento summary un pequeño triángulo. ▸ para details cerrado y ▾ desplegado.

En los navegadores webkit podemos acceder a esta marca identificativa con el pseudoelemento privativo ::-webkit-details-marker

summary::-webkit-details-marker { /* estilos muy chu-chu-chulos como color y font-size*/ } /*o diferenciarlo al desplegarse el contenido*/ details[open] > summary::-webkit-details-marker { }

O ir un paso más allá si no te gustan los triángulos y quieres mostrar tu propia marca:

summary::-webkit-details-marker { display: none } summary:before { content: "+"; } details[open] > summary:before { content: "~"; }

Ver Demo en Codepen

Animación de la apertura y cierre de details

Los navegadores se sirven del shadow DOM (gracias Emilio) aplicando un display: none en línea (como puedes ver en la imagen precedente) a los contenidos de details replegado y quitando dicho estilo al abrirlo.

Esto supone que:

  1. Sea imposible acceder a ese estilo en línea hoy por hoy. Y por la info facilitada en el enlace del párrafo previo (abandono del combinador CSS >>>) parece que nunca.
    1. Por el punto anterior sí podremos animar el despliegue de los contenidos de details de múltiples formas o maneras: con transition's o keyframes (animation's).
    2. El repliegue es imposible de animar con sólo CSS. La razón: al pulsar el summary aplica instantáneamente el display: none y esto conlleva que el cierre (desaparición de los contenidos) sea brusco, sin posiblidad alguna de retrasarlo o anularlo. Y por lo tanto cualquier otra declaración CSS que intentemos aplicar lo hará después de su desaparición.

Todo Junto en una demo

Y como colofón un viejo conocido realizado de forma más sencilla con details y summary: Navegación interna en la misma página desde un sumario o tabla de contenidos con enlace a cada capítulo o apartado:

See the Pen Toggle function & smooth scroll pure HTML & CSS by Kseso by Kseso (@Kseso) on CodePen.

En esta demo juego con otras novedades CSS, como el desplazamiento suave (no saltos) del escroll. En el artículo CSS scroll control tienes los detalles al respecto.

Alterando el despliegue

Vía Twitter me plantea @AntBogarin una cuestión interesante que había pasado por alto: por defecto el contenido replegado se despliega hacia abajo:

No debería plantear mayor problema cambiar este comportamiento, siempre teniendo en cuenta ciertas particularidades y los detalles propios de cada realización. Al igual que se hace con los menús desplegables de múltiples niveles, pero teniendo en cuenta que el despliegue de un details no fuerza el cierre de otros, por lo que hay que prever y evitar los solapamientos.

Una realización rápida y a modo de ejemplo:

See the Pen zrZJzp by Kseso (@Kseso) on CodePen.

Y otro típico menú desplegable con details y summary:

See the Pen adJRzP by Kseso (@Kseso) on CodePen.

Enlaces de interés: lecturas y ayudas

  1. Details y Summary en la especificación W3c
  2. Cross-Browser Polyfills

avatar del Editor del blog

the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso