Neste artigo, examinaremos algumas maneiras simples de estilizar o elemento HTML <details>
, que é um elemento muito útil para revelar e ocultar partes de conteúdo em uma página da web.
É útil ter um elemento de divulgação simples em HTML que não requer JavaScript, mas o estilo padrão do elemento <details>
pode não agradar a todos. Felizmente, é bastante fácil alterar o estilo deste elemento.
A tabela de conteúdos abaixo é um exemplo do elemento <details>
em uso. Adicionamos uma borda simples a ele, junto com algum preenchimento.
Table of Contents
- Introduzindo o Elemento details
- Cores de Fundo, Borda e Preenchimento
- Estilizando o Marcador
- Criando um marcador personalizado para o elemento summary
- Removendo o marcador personalizado
- Usando uma imagem de fundo como marcador
- Usando uma imagem de fundo como marcador com ::after
- Fazendo o elemento summary parecer uma aba
- Limitando a largura do elemento details
- Colocando a seta do marcador no extremo final do summary
- Usando ::after como marcador sem imagem de fundo
- Diversos Extras
- Efeito de hover no elemento detalhes
- Animando a abertura e fechamento do elemento detalhes
- Alterando o conteúdo do sumário em estados abertos e fechados
- Alterando o cursor do sumário
- Alterando os estilos de foco de acessibilidade
- Usando múltiplos elementos detalhes como uma lista de acordeão
- Estilizando um cabeçalho dentro do sumário
- Conclusão
Introduzindo o Elemento Detalhes
Aqui está o código básico para o elemento <details>
:
<details>
<summary>Click me!</summary>
<p>Peekaboo! Here's some hidden content!</p>
</details>
Basicamente, qualquer conteúdo HTML pode ser colocado dentro do elemento <details>
. O elemento <summary>
fornece o prompt para que o usuário clique no elemento para revelar mais conteúdo, e deve ser o primeiro filho do elemento <details>
.
Aqui está um exemplo ao vivo deste código:
Click me!
Peekaboo! Aqui está algum conteúdo oculto!
Vamos ver todas as maneiras pelas quais podemos usar CSS para melhorar a aparência do nosso elemento <details>
.
Cores de Fundo, Borda e Preenchimento
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.
Adicionando uma borda
Como mostrado no sumário acima, uma simples borda pode fazer muito para realçar e definir o elemento <details>
, juntamente com algum preenchimento e um pequeno raio de borda:
details {
padding: 10px;
border: 5px solid #f7f7f7;
border-radius: 3px;
}
Esse é o código simples que usamos acima para estilizar nosso Sumário.
Adicionando alguma cor de fundo
Vamos adicionar uma cor de fundo ao nosso elemento <details>
em vez de uma borda:
details {
padding: 10px;
background-color: #e4eaef;
border-radius: 5px;
}
O resultado é mostrado no Pen abaixo.
A cor de fundo dá melhor definição ao elemento, e o preenchimento ajuda a criar algum espaço dentro dele.
Também podemos dar uma cor de fundo diferente ao elemento <summary>
para distingui-lo do restante do conteúdo, e mudar a cor do texto:
summary {
background-color: #2196F3;
color: white;
padding: 10px;
}
Observe que alterar a cor do texto do elemento <summary>
também altera a cor da seta do marcador. Isso ocorre porque o marcador está realmente anexado ao elemento <summary>
assim como marcadores (como bullets) estão anexados a itens de lista. Veremos abaixo como estilizá-los separadamente.
Estilizando o Marcador
O elemento <summary>
é definido com um display
de list-item
. Assim, a seta padrão (▶) que vem com ele pode ser alterada como os marcadores padrão em itens de lista HTML. Podemos mudar o caractere utilizado e alterar sua cor de forma independente.
Alterando a cor do marcador
Vamos definir o marcador padrão com uma cor diferente. Apenas por diversão, também aumentaremos o tamanho da fonte do marcador. Podemos fazer isso com o pseudo-elemento ::marker
:
summary::marker {
color: #e162bf;
font-size: 1.2em;
}
O resultado é mostrado abaixo.
É uma solução agradável e simples, embora o ::marker
infelizmente não seja suportado no Safari, então veja outras opções abaixo se isso for um problema.
Alterando o espaçamento do marcador
Por padrão, a seta do marcador está bastante próxima ao texto do sumário. Seu list-style-position
é definido como inside
. Se mudarmos para outside
, podemos adicionar espaço entre o texto do sumário e o marcador adicionando algum padding à esquerda. Também precisamos adicionar algum margin à esquerda para que o triângulo não fique pendurado fora do contêiner:
summary {
list-style-position: outside;
margin-left: 30px;
padding: 10px 10px 10px 20px;
border-radius: 5px;
}
O resultado é mostrado abaixo.
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.
Alterando a forma do marcador
O marcador em nosso elemento `<summary>
` não precisa ser um triângulo. Podemos substituí-lo por qualquer caractere que desejarmos:
summary {
list-style-type: '⬇ ';
}
Note que usamos `'⬇ '
` (com um espaço ao lado da seta), que é uma alternativa à espaçamento que tentamos acima.
Agora temos uma seta para baixo em vez de um triângulo. Mas … essa seta para baixo não mudará quando o elemento `<details>
` estiver aberto. Isso ocorre porque o elemento `<details>
` tem dois estados — `fechado
` e `aberto
` — e só definimos o estilo do marcador para o estado `fechado
`. Então, vamos também definir um marcador para o estado `aberto
`:
details[open] > summary {
list-style-type: '⬆ ';
}
Desta vez, usamos uma seta apontando para cima. Isso nos dá o resultado mostrado abaixo.
Droga! Mais uma vez, o Safari nos decepciona, pois também não suporta `list-style-type
` no elemento `<summary>
`. Não desespere, porém, pois veremos soluções mais elaboradas abaixo.
Podemos tentar todos os tipos de outros caracteres, como + e –, ✓ e Χ ou ✗, ⋁ e ⋀ , e até nos divertir com outros caracteres como ★ ou frutas coloridas como 🍏 🍌 🍓 🍋 e 🍐, mas lembre-se de que esses caracteres podem não funcionar em todos os sistemas, então tenha um pouco de cuidado, e novamente, `list-style-type
` certamente não funcionará no Safari.
Criando um Marcador Personalizado para o Elemento summary
Como vimos acima, embora possamos poder definir um caractere diferente para o marcador padrão e dar-lhe estilos como cor e tamanho da fonte, pode haver problemas ao fazê-lo. Uma opção melhor pode ser remover o marcador completamente e criar uma alternativa totalmente personalizada.
Removendo o marcador personalizado
Assim como com os marcadores de itens de lista, podemos remover o marcador completamente:
summary {
list-style: none;
}
/* ah, novamente o Safari */
summary::-webkit-details-marker {
display: none;
}
O padrão list-style: none
funciona em todos os navegadores exceto … (consegue adivinhar?) … Safari. Pelo menos há uma opção proprietária -webkit-
neste caso.
Nota: outra maneira de remover o marcador do elemento <summary>
é dar ao elemento <summary>
um valor de display
diferente de list-item
— como block
ou flex
. Isso funciona em todos os navegadores exceto … (preciso mesmo dizer?) … Safari.
Agora nosso elemento não tem marcador.
Não ter marcador não fornece nenhum indicativo visual de que este elemento é clicável, então não é uma boa ideia deixar assim.
Usando uma imagem de fundo como marcador
Poderíamos colocar uma imagem no fundo, da seguinte forma:
summary {
list-style: none;
padding: 10px 10px 10px 40px;
background: url(arrow.svg) no-repeat 14px 50%;
background-size: 18px;
font-weight: bold;
}
O resultado é mostrado abaixo.
O lado negativo de usar uma imagem de fundo diretamente no elemento `<summary>
` é que não podemos rotacioná-la quando o elemento `<details>
` está aberto, porque as animações não podem ser definidas diretamente nas imagens de fundo em CSS. (Podemos, é claro, usar uma imagem diferente para o estado aberto, mas ainda não poderíamos animá-la, o que é muito mais divertido.) Portanto, se vamos usar uma imagem de fundo, é melhor colocá-la em um elemento que possa ser rotacionado e/ou animado.
Usando uma imagem de fundo como marcador com ::after
Vamos colocar a imagem de fundo dentro de um 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);
}
Aqui está uma demonstração ao vivo deste código.
Usamos display: flex
no elemento `<summary>
` para facilitar a posição do ponteiro horizontalmente.
A vantagem desta configuração é que podemos adicionar animação ao ponteiro. (A animação não parece funcionar no Safari, mas o comportamento é bom o suficiente, e estou ficando um pouco cansado deste navegador!)
Fazendo o elemento summary parecer uma aba
Temos configurado o elemento `<summary>
` com largura total, mas isso não é necessário. Poderíamos fazê-lo parecer mais com uma aba, com esta simples mudança:
summary {
display: inline-flex;
}
Um exemplo é mostrado abaixo.
Limitando a largura do elemento details
Em todos os exemplos até agora, o elemento <details>
se estendeu até a largura total do seu contêiner, pois é um elemento de nível de bloco. No entanto, podemos dar a ele uma largura diferente, se não quisermos que seja tão larga, como width: 50%;
. Ou poderíamos definir para uma exibição em linha para que seja tão larga quanto seu conteúdo:
details {
display: inline-block;
}
Clique no separador abaixo para revelar a largura mais estreita do elemento <details>
.
Tente alterar display: inline-block
para width: 50%
no Pen acima.
Colocando a seta do marcador no extremo do sumário
Vamos fazer algo um pouco diferente agora, colocando a seta do marcador no lado direito do elemento <summary>
. Como temos usado display: flex
, mover a seta para o extremo direito é tão fácil quanto adicionar justify-content: space-between
ao elemento <summary>
:
summary {
display: flex;
justify-content: space-between;
}
Usando ::after como marcador sem uma imagem de fundo
Existem outras maneiras de usarmos ::after
sem uma imagem real. Aqui está um exemplo que usa apenas ::after
com bordas:
summary::after {
content: '';
width: 0;
height: 0;
border-top: 10px solid #15171b;
border-inline: 7px solid transparent;
transition: 0.2s;
}
Aqui está uma demonstração ao vivo.
Agora temos uma seta que gira entre os estados fechado e aberto. Também adicionamos uma bela sombra fosca ao elemento <details>
.
Outra maneira de usar ::after
sem uma imagem é colocar caracteres Unicode dentro da propriedade content
:
summary::after {
content: "\25BC";
transition: 0.2s;
}
Isso define uma forma de triângulo (▼) como nosso marcador, conforme mostrado no demo do CodePen.
Existem milhares de símbolos Unicode, e são bastante divertidos de explorar. Cada um vem com um código como U + 25BC
ou U + 025BC
. Para usar esse código dentro da propriedade content
, pegue os caracteres após o +
e coloque-os dentro das aspas de content
, com um \
na frente: content: "\25BC"
. Se houver um ou mais zeros no início, você pode omiti-los. (Por exemplo, U + 02248
pode se tornar "\02248"
ou "\2248"
.)
Extras Diversos
Até agora, as coisas que fizemos acima são mais do que suficientes, mas há outras coisas com as quais podemos nos divertir, então vamos apenas brincar com algumas delas aqui.
Efeito de hover no elemento details
Podemos definir vários efeitos de hover no elemento <details>
. Por exemplo, podemos fazer algo assim:
details {
transition: 0.2s background linear;
}
details:hover {
background: #dad3b1;
}
Enquanto estamos nisso, também vamos fazer a transição da cor do texto do <summary>
no estado open
:
details > summary {
transition: color 1s;
}
details[open] > summary {
color: #d9103e;
}
O resultado é mostrado abaixo.
Poderíamos também simplesmente definir uma mudança de plano de fundo no elemento <summary>
em vez disso.
Animando a abertura e fechamento do elemento details
Haha, enganei você! Parece que não é possível animar a abertura e fechamento do elemento <details>
. De acordo com a MDN:
Infelizmente, neste momento, não há uma maneira incorporada de animar a transição entre aberto e fechado.
No entanto, podemos nos divertir um pouco animando o conteúdo do elemento <details>
. Por exemplo, poderíamos fazer o conteúdo desaparecer quando revelado:
details article {
opacity: 0;
}
details[open] article {
animation: fadeIn .75s linear forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
O resultado é mostrado abaixo.
Outra técnica poderia ser fazer o conteúdo deslizar, assim:
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);
}
}
O resultado é mostrado abaixo.
É um pouco exagerado, e talvez seja demais, mas vale a pena tentar. Infelizmente, essas animações funcionam apenas na primeira vez que o elemento é clicado (a menos que as ferramentas do desenvolvedor do navegador estejam abertas, por algum motivo estranho!). Basicamente, você precisa da intervenção do JavaScript para que o efeito funcione repetidamente.
Mudando o conteúdo do resumo em estados abertos e fechados
Nos exemplos acima, o <select>
sempre teve o mesmo texto, seja o elemento <details>
aberto ou fechado. Mas poderíamos mudar isso. Primeiro, vamos deixar o texto atual “Clique em mim” no lugar, mas também adicionar algum texto extra para cada estado usando o pseudo-elemento ::after
:
summary::after {
content: " to show hidden content";
}
details[open] summary::after {
content: " to hide extra content";
}
Isso nos dá o resultado mostrado abaixo.
Mudando o cursor do resumo
O cursor padrão (ou ponteiro do mouse) para o elemento `<details>
` é meio estranho. É uma seta padrão na maior parte do tempo, e um ponteiro de texto (ou I-beam) ao passar o mouse sobre o texto `<summary>
`.
Por diversão, vamos mudar para o cursor de mão (ou “ponteiro”):
summary {
cursor: pointer;
}
Isso define o ponteiro do mouse como uma mão ao passar o mouse em qualquer lugar sobre o elemento `<summary>
`, como mostrado abaixo.
Poderíamos definir o cursor no elemento `<details>
` em vez disso, o que forçaria o cursor de mão em todo o elemento `<details>
`. Prefiro mantê-lo apenas no que devemos clicar.
Mudando os estilos de foco de acessibilidade
Se navegarmos por uma página usando o teclado, podemos usar a tecla Tab para chegar ao elemento `<details>
` e, em seguida, abri-lo apertando retorno. Durante o foco, o elemento `<summary>
` tem um contorno padrão. A imagem abaixo mostra como isso se parece em vários navegadores.
Eles são muito parecidos: principalmente um contorno simples, escuro (azul ou preto), sólido, com cerca de `3px
` de largura.
Há muitos estilos que poderíamos definir para o elemento `<details>
` focado, mas vamos fazer algo simples aqui como prova de conceito, mudando o contorno para uma linha tracejada vermelha:
summary:focus {outline: none;}
summary:focus-visible {outline: 3px dotted #ff0060;}
summary {padding: 10px;}
Por padrão, o contorno de foco não é exibido quando clicamos no elemento `<summary>
`. Mas se alterarmos o estilo de foco, esse estilo é exibido mesmo para usuários não-teclado (ou seja, quando clicamos no elemento `<details>
` com o mouse). Então, no código acima, definimos o `outline
` como `none
` e, em vez disso, usamos `focus-visible
` para definir os estilos, pois isso significa que os estilos de foco só serão visíveis para usuários de teclado (para quem isso é realmente útil).
A imagem abaixo mostra nosso novo estilo.
Aqui está uma demonstração ao vivo.
Poderíamos nos divertir muito com isso, usando animações, cores de fundo e assim por diante quando o elemento `<details>
` estiver em foco. Vou deixar para você experimentar mais.
Usando múltiplos elementos de detalhes como uma lista de acordeão
Existem propostas para coordenar múltiplos elementos de detalhes de tal maneira que um feche quando outro seja aberto. A especificação HTML até propõe um atributo `name
` compartilhado entre múltiplos elementos `<details>
` para esse propósito.
Não há atualmente uma maneira de fazer isso apenas com HTML e CSS, mas existem alguns exemplos engenhosos de como fazê-lo com JavaScript (como aqui, aqui e aqui).
O melhor que podemos fazer com CSS é estilizar o elemento atualmente aberto de forma diferente dos outros, usando algumas das técnicas que cobrimos acima.
Aqui está um exemplo simples:
details {
background-color: #2196F3;
}
details[open] {
background-color: #ce0e99;
}
Estilizando um título dentro do sumário
Alguns desenvolvedores, preocupados com a estrutura do seu HTML, gostam de colocar um elemento de título dentro do elemento <summary>
. Se isso é útil ou não é motivo de debate, mas a renderização padrão não é agradável, com o título localizado na linha abaixo da seta. Isso pode ser corrigido definindo o título como display: inline
ou display: inline-block
:
summary h2 {
display: inline;
}
Você pode ver uma demonstração disso no CodePen.
Conclusão
Como tentamos mostrar acima, existem muitas maneiras simples de estilizar o elemento <details>
. Definir bordas, preenchimento e cores de fundo é fácil e isso já melhora significativamente a aparência. Algumas das técnicas para estilizar o marcador padrão são muito úteis, mas considerando que a Forrest’s fruit company () tem tantos problemas com o estilo do marcador, pode ser melhor evitar essa opção, em favor de criar um marcador totalmente personalizado. (Dito isto, estilizar o marcador não quebra o elemento <details>
no Safari.)
Houve tentativas de animar a abertura e fechamento do elemento <details>
apenas com CSS, mas são, no máximo, engenhosas, então não vale a pena tentar entrar nesse buraco de coelho. Se você realmente deseja animação de abertura e fechamento, precisará de JavaScript.
Para saber mais sobre o elemento <details>
, confira o seguinte:
Se você descobrir outras maneiras legais de estilizar o elemento <details>
, me avise no Twitter, e talvez possamos apresentá-las aqui.
Source:
https://www.sitepoint.com/style-html-details-element/