Descubra como funcionam os elementos de detalhes e resumo muito úteis e onde usá-los.
Uma seta de expansão, às vezes conhecida como widget de divulgação, é um controle de interface do usuário que oculta e mostra conteúdo. Se você estiver lendo isso em web.dev
e
a janela de visualização tiver menos de 106 ems de largura, clicar em "Nesta página" vai revelar o
sumário desta seção. Se ele não aparecer, diminua o navegador para
ver a navegação do sumário nesta página como uma seta de expansão.
A interface gráfica do usuário acordeão é uma série de widgets de divulgação empilhados verticalmente. Um caso de uso comum para o acordeão é uma página de perguntas frequentes. Nesse caso, um FAQ em acordeão contém uma lista de perguntas visíveis. Quando clicada, a pergunta abre ou "revela" a resposta.
O jQuery inclui um padrão de interface do usuário de acordeão
desde pelo menos 2009. A solução original de acordeão sem JavaScript incluía
transformar cada pergunta das Perguntas frequentes em um <label>
seguido da marca de seleção que ele rotulava e
mostrar a resposta <div>
quando a marca de seleção era marcada. O CSS era
algo assim:
#FAQ [type="checkbox"] + div.answer {
/* all the answer styles */
display: none;
}
#FAQ [type="checkbox"]:checked + div.answer {
display: block;
}
Por que o histórico? Widgets de divulgação, como acordeões, sem JavaScript ou hacks de controle de formulário, são uma adição relativamente recente. Os elementos
<details>
e
<summary>
só têm suporte total em navegadores modernos desde janeiro de 2020.
Agora é possível criar widgets de divulgação funcionais, embora menos atraentes, com HTML semântico.
Os elementos <details>
e <summary>
são tudo o que você precisa: eles são uma
maneira integrada de lidar com a expansão e o recolhimento de conteúdo. Quando um usuário clica ou
toca em um <summary>
ou solta a tecla Enter quando o <summary>
está em foco, o conteúdo do <details>
principal fica visível.
Como todo conteúdo semântico, você pode melhorar progressivamente os recursos e a aparência padrão. Nesse caso, apenas um pouco de CSS foi adicionado:
Isso significa que este CodePen (e todos os exemplos do CodePen) não tem JavaScript.
Alternar a visibilidade com o atributo open
O elemento <details>
é o contêiner do widget de divulgação. O <summary>
é o resumo ou a legenda do <details>
pai. O resumo é sempre exibido, funcionando como um botão que alterna a exibição do restante do conteúdo do elemento pai. Ao interagir com o <summary>
, a exibição dos
elementos irmãos do resumo autônomo é alternada ao ativar o atributo open
do elemento <details>
.
O atributo open
é booleano. Se estiver presente, não importa o valor ou a falta dele, isso indica que todo o conteúdo de <details>
é mostrado ao usuário. Se o atributo open
não estiver presente, apenas o conteúdo do
<summary>
será mostrado.
Como o atributo open
é adicionado e removido automaticamente à medida que o usuário
interage com o controle, ele pode ser usado em CSS para estilizar o elemento
de maneira diferente com base no estado dele.
É possível criar um acordeão com uma lista de vários elementos <details>
, cada um com um filho <summary>
. Omitir o atributo open
no HTML significa que todos os
<details>
serão recolhidos ou fechados, com apenas os cabeçalhos de resumo
visíveis quando a página for carregada. Cada cabeçalho é o abridor do restante do conteúdo no
<details>
pai. Se você incluir o atributo open
no HTML, o <details>
será renderizado expandido, com o conteúdo visível, quando a página for carregada.
O conteúdo oculto no estado recolhido pode ser pesquisado em alguns navegadores, mas não em outros, mesmo que não faça parte do DOM. Se você pesquisar no Edge ou no Chrome, os detalhes que contêm um termo de pesquisa vão ser expandidos para mostrar a ocorrência. Esse comportamento não é replicado no Firefox ou Safari.
O <summary>
precisa ser o primeiro filho de um elemento <details>
, representando um resumo, uma legenda ou uma legenda para o restante do conteúdo do elemento <details>
pai em que ele está aninhado. O conteúdo do elemento <summary>
pode ser qualquer conteúdo de cabeçalho, texto simples ou HTML que possa ser usado em um
parágrafo.
Ativar/desativar o marcador de resumo
Nos dois Codepens anteriores, há uma seta no lado inline-start do resumo. Normalmente, uma seta de expansão é apresentada na tela, um
pequeno triângulo que gira (ou torce) para indicar o status aberto ou fechado e
um rótulo ao lado do triângulo. O conteúdo do elemento <summary>
rotula o
widget de divulgação.
A seta giratória na parte de cima de cada seção é um
::marker
definido no elemento
<summary>
. Assim como os itens de lista, o elemento <summary>
é compatível com a propriedade abreviada list-style
e as propriedades por extenso, incluindo list-style-type
.
É possível estilizar o triângulo de abertura com CSS, incluindo a mudança do marcador usado de um triângulo para qualquer outro tipo de marcador, incluindo uma imagem com list-style-image
.
Para aplicar outros estilos, use um seletor semelhante a
details summary::marker
. O pseudoelemento ::marker
aceita apenas um número limitado de estilos. Remover o ::marker
e substituí-lo pelo
::before
mais fácil de estilizar é uma prática comum. Os estilos CSS mudam um pouco o estilo do conteúdo gerado
com base na presença (ou ausência) do atributo aberto. Você pode
remover o ícone do widget de divulgação definindo list-style: none
ou definir o
conteúdo
do marcador como none
, mas sempre inclua indicadores visuais para
informar aos usuários com visão que o conteúdo do resumo alterna para mostrar e ocultar conteúdo.
details summary::before {
/* all the styles */
}
details[open] summary::before {
/* changes applied when open only */
}
Este exemplo remove o marcador padrão e adiciona conteúdo gerado para criar um
+
quando os detalhes são fechados e um -
quando são abertos.
Se você quiser que o bloco de detalhes fique aberto por padrão, inclua o atributo open
na
tag de abertura <details>
. Você também pode adicionar espaço entre cada caixa de diálogo e fazer a transição da rotação do marcador criado com conteúdo gerado para melhorar a aparência:
Como os erros são tratados
Se você não incluir um <summary>
, o navegador vai criar um para você, com um
marcador e a palavra "detalhes". Esse resumo faz parte de uma raiz shadow e, portanto, não tem estilos de resumo CSS do autor aplicados.
Se você incluir um <summary>
, mas ele não for o primeiro elemento no
<details>
, o navegador ainda vai mostrar o resumo corretamente. Não vai falhar se você incluir um link, um rótulo ou outro elemento interativo no resumo, mas os navegadores processam o conteúdo interativo de maneira diferente.
Por exemplo, se você incluir um link em um resumo, alguns navegadores vão adicionar o resumo e o link à ordem de tabulação padrão, mas outros não vão focar no link por padrão. Se você clicar em um <label>
aninhado em um <summary>
,
alguns navegadores vão dar foco ao controle de formulário associado. Outros navegadores
dão foco ao controle de formulário e alternam o <details>
aberto ou fechado.
A interface HTMLDetailsElement
Como todos os elementos HTML, o
HTMLDetailsElement
herda todas as propriedades, métodos e eventos de
HTMLElement
e
adiciona a propriedade de instância open
e um evento toggle
. A propriedade HTMLDetailsElement.open
é um valor booleano que reflete o atributo HTML
open
, indicando se o conteúdo do elemento
(sem contar o <summary>
) deve ser mostrado ao usuário. O evento de alternância é
acionado quando o elemento <details>
é aberto ou fechado. É possível detectar esse evento usando addEventListener()
.
Se você quiser escrever um script para fechar os detalhes abertos quando o usuário abrir
outros detalhes, remova o atributo "open" usando
removeAttribute("open")
:
Este é o único exemplo que usa JavaScript. Você provavelmente não precisa de JavaScript, exceto para fechar outros widgets abertos.
Lembre-se de que <details>
e <summary>
podem ser estilizados e até mesmo usados para criar dicas.
No entanto, se você for usar esses elementos semânticos em casos de uso em que a semântica nativa não corresponde, mantenha sempre a acessibilidade.
O HTML, na maior parte, é acessível por padrão. Nosso trabalho como desenvolvedores é garantir que nosso conteúdo permaneça acessível.
Teste seu conhecimento
Teste seus conhecimentos sobre detalhes e resumo.
O <summary>
precisa ser o primeiro filho de qual elemento?
<p>
<details>
<fieldset>