20 Maneras Sencillas de Estilar el Elemento HTML details

En este artículo, veremos algunas formas sencillas de dar estilo al elemento HTML <details>, que es un elemento muy útil para revelar y ocultar fragmentos de contenido en una página web.

Es útil tener un elemento de divulgación simple en HTML que no requiera JavaScript, pero el estilo predeterminado del elemento <details> podría desanimar a algunos. Afortunadamente, es bastante fácil cambiar el estilo de este elemento.

El índice de contenido a continuación es un ejemplo del elemento <details> en uso. Hemos agregado un borde simple a él, junto con un poco de relleno.

Table of Contents

Introducción del Elemento Detalles

Aquí está el código básico para el elemento <details>:

<details>
  <summary>Click me!</summary>
  <p>Peekaboo! Here's some hidden content!</p>
</details>

Básicamente, cualquier contenido HTML puede colocarse dentro del elemento <details>. El elemento <summary> proporciona el indicador para que el usuario haga clic en el elemento para revelar más contenido, y debe ser el primer hijo del elemento <details>.

Aquí hay un ejemplo en vivo de este código:

Click me!

¡Peekaboo! ¡Aquí hay contenido oculto!

Veamos todas las formas en que podemos usar CSS para mejorar la apariencia de nuestro elemento <details>.

Colores de Fondo, Bordes y Relleno

A really simple way to enhance the look of the <details> element is to add some padding along with a border or some background colors.

Agregar un borde

Como se muestra en el índice de contenido anterior, un simple borde puede hacer mucho para mejorar y definir el elemento <details>, junto con un poco de relleno y un leve radio de borde:

details {
  padding: 10px; 
  border: 5px solid #f7f7f7;
  border-radius: 3px;
}

Ese es el código simple que hemos usado arriba para dar estilo a nuestro Índice.

Agregar un poco de color de fondo

Agreguemos un color de fondo a nuestro elemento <details> en lugar de un borde:

details {
  padding: 10px;
  background-color: #e4eaef;
  border-radius: 5px;
}

El resultado se muestra en el lápiz a continuación.

El color de fondo da mejor definición al elemento, y el relleno ayuda a crear algo de espacio dentro de él.

También podemos darle un color de fondo diferente al elemento <summary> para distinguirlo del resto del contenido, y cambiar su color de texto:

summary {
  background-color: #2196F3;
  color: white;
  padding: 10px;
}

Tenga en cuenta que cambiar el color del texto del elemento <summary> también cambia el color de la flecha del marcador. Eso se debe a que el marcador está realmente adjunto al elemento <summary> de la misma manera que los marcadores (como los puntos) están adjuntos a los elementos de lista. Veremos a continuación cómo estilizarlos por separado.

Estilizando el Marcador

El elemento <summary> está configurado con un display de list-item. Por lo tanto, la flecha predeterminada (▶) que viene con él puede ser alterada de la misma manera que los marcadores predeterminados en los elementos de lista HTML. Podemos cambiar el carácter que se usa y cambiar su color de forma independiente.

Cambiando el color del marcador

Establezcamos el marcador predeterminado en un color diferente. Solo por diversión, también aumentemos el tamaño de fuente del marcador. Podemos hacer esto con el pseudo-elemento ::marker:

summary::marker {
  color: #e162bf;
  font-size: 1.2em;
}

El resultado se muestra a continuación.

Es una solución agradable y simple, aunque desafortunadamente ::marker no es compatible con Safari, así que vea otras opciones a continuación si eso es un impedimento.

Cambiando el espaciado del marcador

Por defecto, la flecha del marcador está bastante cerca del texto del resumen. Su list-style-position está configurado en inside. Si lo cambiamos a outside, podemos agregar espacio entre el texto del resumen y el marcador agregando un poco de relleno izquierdo. También necesitamos agregar un margen izquierdo para que el triángulo no cuelgue fuera del contenedor:

summary {
  list-style-position: outside;
  margin-left: 30px;
  padding: 10px 10px 10px 20px;
  border-radius: 5px;
}

El resultado se muestra a continuación.

I’ve exaggerated the spacing between the arrow marker and the summary text just to make it obvious. Unfortunately, using list-style-position: outside; with the <summary> element doesn’t work in Safari. Fortunately, there are other options, as we’ll see below.

Cambiando la forma del marcador

El marcador en nuestro elemento `

` no tiene que ser un triángulo. Podemos reemplazarlo con cualquier carácter que nos plazca:

summary {
  list-style-type: '⬇ ';
} 

Tenga en cuenta que hemos utilizado '⬇ ' (con un espacio al lado de la flecha), que es una alternativa a la separación que probamos anteriormente.

Ahora tenemos una flecha hacia abajo en lugar de un triángulo. Pero … esa flecha hacia abajo no cambiará cuando el elemento `

` esté abierto. Eso es porque el elemento `

` tiene dos estados: cerrado y abierto, y solo hemos establecido el estilo del marcador para el estado cerrado. Así que también establezcamos un marcador para el estado abierto:
details[open] > summary {
  list-style-type: '⬆ ';
}

Esta vez, hemos utilizado una flecha apuntando hacia arriba. Esto nos da el resultado que se muestra a continuación.

¡Maldición! Una vez más, Safari nos decepciona, ya que tampoco admite list-style-type en el elemento `

`. Sin embargo, no desespere, ya que veremos soluciones más elegantes a continuación.

Podemos probar todo tipo de otros caracteres, como + y –, ✓ y Χ o ✗, ⋁ y ⋀, e incluso divertirnos con otros caracteres como ★ o frutas coloridas como 🍏 🍌 🍓 🍋 y 🍐, pero recuerde que estos caracteres pueden no funcionar en todos los sistemas, así que tenga un poco de cuidado, y una vez más, list-style-type ciertamente no funcionará en Safari.

Creación de un Marcador Personalizado para el Elemento summary

Como vimos arriba, aunque podamos establecer un carácter diferente para el marcador predeterminado y darle estilos como color y tamaño de fuente, puede haber problemas al hacerlo. Una mejor opción podría ser eliminar el marcador por completo y crear una alternativa completamente personalizada.

Eliminando el marcador personalizado

Al igual que con los marcadores de elementos de lista, podemos eliminar el marcador por completo:

summary  {
  list-style: none;
}

/* ¡vaya, Safari otra vez */

summary::-webkit-details-marker {
  display: none;
}

El estándar list-style: none funciona en todos los navegadores excepto … (¿puedes adivinar?) … Safari. Al menos hay una opción -webkit- propietaria en este caso.

Nota: otra forma de eliminar el marcador del elemento <summary> es darle al elemento <summary> un valor de display distinto de list-item — como block o flex. Esto funciona en todos los navegadores excepto … (¿incluso necesito decirlo?) … Safari.

Ahora nuestro elemento no tiene marcador.

No tener marcador no da ninguna indicación visual de que este elemento es clickeable, por lo que no es una buena idea dejarlo así.

Usar una imagen de fondo como marcador

Podríamos colocar una imagen en el fondo, de la siguiente manera:

summary {
  list-style: none;
  padding: 10px 10px 10px 40px;
  background: url(arrow.svg) no-repeat 14px 50%;
  background-size: 18px;
  font-weight: bold;
}

El resultado se muestra a continuación.

El inconveniente de usar una imagen de fondo directamente en el elemento <summary> es que no podemos rotarla cuando el elemento <details> está abierto, porque las animaciones no se pueden establecer directamente en imágenes de fondo en CSS. (Podríamos, por supuesto, usar una imagen diferente para el estado abierto, pero aún no podríamos animarla, lo cual es mucho más divertido). Por lo tanto, si vamos a usar una imagen de fondo, es mejor colocarla en un elemento que pueda rotarse y/o animarse.

Usar una imagen de fondo como marcador con ::after

Coloquemos la imagen de fondo dentro de un pseudo-elemento ::after:

summary {
  display: flex;
}

summary::after {
  content: '';
  width: 18px;
  height: 10px;
  background: url('arrow.svg');
  background-size: cover;
  margin-left: .75em;
  transition: 0.2s;
}

details[open] > summary::after {
  transform: rotate(180deg);
}

Aquí hay una demostración en vivo de este código.

Hemos usado display: flex en el elemento <summary> para facilitar la posición horizontal de la flecha.

Lo bueno de esta configuración es que podemos agregar animación a la flecha. (La animación no parece funcionar en Safari, pero el comportamiento es lo suficientemente bueno, ¡y estoy empezando a cansarme de este navegador!)

Hacer que el elemento summary se vea como una pestaña

Hemos estado configurando el elemento <summary> con ancho completo, pero no tiene por qué ser así. Podríamos hacer que se parezca más a una pestaña, con este simple cambio:

summary {
  display: inline-flex;
}

Se muestra un ejemplo a continuación.

Limitando el ancho del elemento details

En todos nuestros ejemplos hasta ahora, el elemento `<details>` se ha extendido hasta el ancho total de su contenedor, ya que es un elemento de nivel de bloque. Sin embargo, podemos darle un ancho diferente si no queremos que sea tan ancho, como `width: 50%;`. O podríamos establecerlo para que tenga un display en línea para que sea tan ancho como su contenido:

details {
  display: inline-block;
}

Haz clic en la pestaña a continuación para revelar el ancho más estrecho del elemento `<details>`.

Intenta cambiar `display: inline-block` a `width: 50%` en el Pen anterior.

Colocando la flecha del marcador en el extremo lejano del resumen

Ahora hagamos algo un poco diferente, colocando la flecha del marcador en el lado derecho del elemento `<summary>`. Como hemos estado usando `display: flex`, mover la flecha al extremo derecho es tan fácil como agregar `justify-content: space-between` al elemento `<summary>`:

summary {
  display: flex;
  justify-content: space-between;
}

Usar ::after como marcador sin una imagen de fondo

Hay otras maneras en que podríamos usar `::after` sin una imagen real. Aquí hay un ejemplo que solo usa `::after` con bordes:

summary::after {
  content: '';
  width: 0; 
  height: 0; 
  border-top: 10px solid #15171b;
  border-inline: 7px solid transparent;
  transition: 0.2s;
}

Aquí hay una demostración en vivo.

Ahora tenemos una flecha que rota entre el estado cerrado y abierto. También hemos agregado una agradable sombra arrojada al elemento `<details>`.

Otra forma de usar `::after` sin una imagen es colocar caracteres Unicode dentro de la propiedad `content`:

summary::after {
  content: "\25BC";
  transition: 0.2s;
}

Esto establece una forma de triángulo (▼) como nuestro marcador, como se muestra en este demo de CodePen.

Existen miles de símbolos Unicode, y son bastante divertidos de explorar. Cada uno viene con un código como U + 25BC o U + 025BC. Para usar ese código dentro de la propiedad content, toma los caracteres después del + y colócalos dentro de las comillas de content, con una \ al frente: content: "\25BC". Si hay uno o más ceros al inicio, puedes omitirlos. (Por ejemplo, U + 02248 puede convertirse en "\02248" o "\2248".)

Extras Diversos

Hasta ahora, las cosas que hemos hecho arriba son más que suficientes, pero hay otras cosas con las que podemos divertirnos, así que juguemos con algunas de ellas aquí.

Efecto de pasar el ratón sobre el elemento detalles

Podemos establecer varios efectos al pasar el ratón sobre el elemento <details>. Por ejemplo, podríamos hacer algo como esto:

details {
  transition: 0.2s background linear;
}

details:hover {
  background: #dad3b1;
}

Mientras estamos en ello, también vamos a cambiar el color del texto del <summary> en el estado open:

details > summary {
  transition: color 1s;
}

details[open] > summary {
  color: #d9103e;
}

El resultado se muestra a continuación.

También podríamos simplemente establecer un cambio de fondo en el elemento <summary> en su lugar.

Animando la apertura y cierre del elemento detalles

¡Jaja, te engañé! Parece que no es posible animar la apertura y cierre del elemento <details>. Según MDN:

Desafortunadamente, en este momento, no hay una manera incorporada para animar la transición entre abierto y cerrado.

Sin embargo, podemos divertirnos un poco animando el contenido del elemento <details>. Por ejemplo, podríamos hacer que el contenido aparezca con un fundido al revelarse:

details article {
  opacity: 0;
}

details[open] article {
  animation: fadeIn .75s linear forwards;
}

@keyframes fadeIn {
 0% {
   opacity: 0;
 }
 100% {
   opacity: 1;
 }
} 

El resultado se muestra a continuación.

Otro truco podría ser hacer que el contenido se deslice, así:

details {
  overflow: hidden;
}

details[open] article {
  animation: animateUp .5s linear forwards;
}

@keyframes animateUp {
  0% {
    opacity: 0;
    transform: translatey(100%);
  }
  100% {
    opacity: 1;
    transform: translatey(0);
  }
}

El resultado se muestra a continuación.

Es un poco cursi, y tal vez sea excesivo, pero vale la pena intentarlo de todos modos. Desafortunadamente, estas animaciones solo funcionan la primera vez que se hace clic en el elemento (a menos que estén abiertos los devtools del navegador, por alguna extraña razón!). Básicamente necesitas la intervención de JavaScript para que el efecto funcione repetidamente.

Cambiar el contenido del resumen en estados abierto y cerrado

En las demostraciones anteriores, el <select> siempre ha tenido el mismo texto, independientemente de si el elemento <details> está abierto o cerrado. Pero podríamos cambiar eso. Primero, dejemos el texto actual “Haz clic aquí” en su lugar, pero también agreguemos algo de texto adicional para cada estado utilizando el pseudoelemento ::after:

summary::after {
  content: " to show hidden content";
}

details[open] summary::after {
  content: " to hide extra content";
}

Eso nos da el resultado que se muestra a continuación.

Cambiar el cursor del resumen

El cursor predeterminado (o puntero del mouse) para el elemento `<details>` es algo extraño. Es una flecha estándar en su mayoría, y un puntero de texto (o I-beam) al pasar el mouse sobre el texto del `<summary>`.

Por diversión, cambiemos al cursor de mano (o “puntero”):

summary {
  cursor: pointer;
}

Esto establece el puntero del mouse como una mano al pasar el mouse sobre cualquier parte del elemento `<summary>`, como se muestra a continuación.

Podríamos establecer el cursor en el elemento `<details>` en su lugar, lo que obligaría al cursor de mano en todo el elemento `<details>`. Sin embargo, prefiero mantenerlo solo en lo que se supone que debemos hacer clic.

Cambiando los estilos de enfoque de accesibilidad

Si estamos navegando por una página mediante el teclado, podemos acceder al elemento `<details>` y luego abrirlo presionando retorno. Durante el enfoque, el elemento `<summary>` tiene un contorno predeterminado. La imagen a continuación muestra cómo se ve esto en varios navegadores.

Son bastante similares: principalmente un contorno simple, oscuro (azul o negro), sólido que tiene aproximadamente `3px` de ancho.

Podemos establecer muchos estilos para el elemento `<details>` enfocado, pero hagamos algo simple aquí como prueba de concepto, cambiando el contorno a una línea roja punteada:

summary:focus {outline: none;}
summary:focus-visible {outline: 3px dotted #ff0060;}
summary {padding: 10px;}

De manera predeterminada, el contorno de enfoque no se muestra cuando hacemos clic en el elemento <summary>. Pero si cambiamos el estilo de enfoque, ese estilo se muestra incluso a usuarios no teclado (es decir, cuando hacemos clic en el elemento <details> con un mouse). Entonces, en el código anterior, hemos establecido el outline en none y en su lugar hemos utilizado focus-visible para establecer los estilos, ya que esto significa que los estilos de enfoque solo serán visibles para los usuarios de teclado (para quienes es realmente útil).

La imagen a continuación muestra nuestro nuevo estilo.

Aquí tienes una demo en vivo.

Podríamos tener mucha diversión con esto, utilizando animaciones, colores de fondo y demás cuando el elemento <details> está en enfoque. Te dejo a ti experimentar más.

Usar múltiples elementos de detalles como una lista de acordeón

Existen propuestas para coordinar múltiples elementos de detalles de tal manera que uno se cierre cuando otro se abra. La especificación HTML incluso propone un atributo name compartido entre múltiples elementos <details> con este fin.

No hay una manera actual de hacerlo solo con HTML y CSS, pero hay algunos ejemplos ingeniosos que lo logran con JavaScript (como aquí, aquí y aquí).

Lo mejor que podemos hacer con CSS es dar estilo al elemento actualmente abierto de manera diferente a los demás, utilizando algunas de las técnicas que hemos cubierto anteriormente.

Aquí hay un ejemplo simple:

details {
  background-color: #2196F3;
}

details[open] {
  background-color: #ce0e99;
}

Estilizando un encabezado dentro del resumen

Algunos desarrolladores, preocupados por la estructura de su HTML, prefieren colocar un elemento de encabezado dentro del elemento <summary>. Si eso es útil o no está en discusión, pero la representación predeterminada no es agradable, con el encabezado situado en la línea debajo de la flecha. Esto puede arreglarse estableciendo el encabezado en display: inline o display: inline-block:

summary h2 {
  display: inline;
}

Puedes ver una demostración de esto en CodePen.

Conclusión

Como hemos intentado mostrar anteriormente, hay muchas formas sencillas de estilizar el elemento <details>. Establecer bordes, padding y colores de fondo es fácil, y estos por sí solos mejoran mucho la apariencia. Algunas de las técnicas para estilizar el marcador predeterminado son muy útiles, pero dado que Forrest’s fruit company () tiene tantos problemas con el estilo del marcador, puede ser mejor desviarse de esa opción, en favor de crear un marcador personalizado completamente. (Dicho esto, estilizar el marcador no rompe el elemento <details> en Safari).

Se han intentado animar la apertura y cierre del elemento <details> solo con CSS, pero son más bien trucos, por lo que no vale la pena intentar caer en ese agujero de conejo. Si realmente deseas una apertura y cierre animados, necesitarás JavaScript.

Para obtener más información sobre el elemento <details>, consulta lo siguiente:

Si se te ocurre alguna otra forma interesante de estilizar el elemento <details>, avísame en Twitter, y podríamos incluirlas aquí.

Source:
https://www.sitepoint.com/style-html-details-element/