Detalhes e resumo

Descubra como os detalhes e elementos de resumo muito úteis funcionam e onde usá-los.

Um widget de declaração é um controle de interface do usuário que oculta e mostra conteúdo. Se você estiver lendo isso no web.dev e sua janela de visualização tiver menos de 106 ems de largura, clicar em "Nesta página" acima deste parágrafo revelará o índice dessa seção. Se essa opção não estiver disponível, reduza o navegador para que a navegação do sumário nesta página seja mostrada como um widget de divulgaçã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 a interface do usuário do Acordeão é a página de Perguntas frequentes em muitos sites. Uma seção de Perguntas frequentes do accordion contém uma lista de perguntas visíveis. Ao clicar em uma pergunta, a resposta a essa pergunta é expandida, ou "divulga".

O jQuery inclui um padrão de interface de usuário sanfona desde pelo menos 2009. A solução original de acordeão sem JavaScript incluía tornar cada pergunta de perguntas frequentes um <label> seguido pela marca de seleção rotulada e, em seguida, exibir a resposta <div> quando a marca de seleção estava marcada. O CSS era mais ou menos assim:

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

Por que a história? Os widgets de divulgação, como accordions, sem JavaScript ou hacks de controle de formulário, são uma adição relativa. Os elementos <details> e <summary> só têm suporte total em todos os navegadores mais recentes desde janeiro de 2020. Agora é possível criar widgets funcionais, embora menos atraentes, de divulgação usando apenas HTML semântico. Os elementos <details> e <summary> são tudo de que você precisa: eles são uma forma integrada de processar conteúdos que podem ser expandidos e recolhidos. Quando um usuário clica ou toca em <summary> ou libera a tecla Enter quando <summary> está em foco, o conteúdo do <details> pai fica visível.

Como em todo o conteúdo semântico, você pode melhorar progressivamente os recursos e a aparência padrão. Nesse caso, um pequeno pedaço de CSS foi adicionado, mas nada mais:

Esses Codepenss não contêm JavaScript.

Como alternar a visibilidade: o atributo open

O elemento <details> é o contêiner do widget de declaração. O <summary> é o resumo ou a legenda da <details> mãe. O resumo é sempre mostrado, agindo como um botão que alterna a exibição do restante do conteúdo do elemento pai. A interação com o <summary> alterna a exibição dos irmãos de resumo autorotulados, alternando o atributo open do elemento <details>.

O atributo open é booleano. Se estiver presente, independentemente do valor ou da falta dele, ele indica que todo o conteúdo de <details> é mostrado ao usuário. Se o atributo open não estiver presente, somente 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 no CSS para estilizar o elemento de maneira diferente com base no estado.

É possível criar um acordeão com uma lista de vários elementos <details>, cada um com um filho <summary>. A omissão do atributo open no HTML significa que <details> será recolhido, ou fechado, com apenas os títulos do resumo visíveis quando a página for carregada. Cada cabeçalho abre o 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 o conteúdo recolhido não faça parte do DOM. Se você pesquisar no Edge ou no Chrome, os detalhes que contêm um termo de pesquisa serão expandidos para mostrar a ocorrência. Esse comportamento não é replicado no Firefox ou no Safari.

O <summary> precisa ser o primeiro filho de um elemento <details>, representando um resumo, legenda ou legenda para o restante do conteúdo do elemento <details> pai em que 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.

Como alternar o marcador de resumo

Nos dois Codepenss anteriores, a seta para o lado inline-start do resumo vai aparecer. Um widget de divulgação normalmente é apresentado na tela usando um pequeno triângulo que gira (ou gira) para indicar o status aberto/fechado, com um rótulo ao lado do triângulo. O conteúdo do elemento <summary> rotula o widget de declaraçã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> oferece suporte à propriedade abreviada list-style e às propriedades longas, incluindo list-style-type. É possível definir o estilo do triângulo de divulgação 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, que é mais fácil de estilizar, é uma prática comum, com estilos CSS mudando ligeiramente o estilo do conteúdo gerado com base na presença (ou ausência) do atributo aberto. É possível 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 deficiência visual que o conteúdo do resumo é um botão de ativação que mostra e oculta o conteúdo após a ativação.

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 uma + quando os detalhes são fechados e uma - quando os detalhes estão abertos.

Se você quiser que o bloco de detalhes seja 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 o conteúdo gerado para melhorar a aparência:

Como os erros são tratados

Se você não incluir uma <summary>, o navegador vai criar uma para você: com um marcador e a palavra "detalhes". Esse resumo faz parte de uma raiz paralela e, portanto, não terá estilos de resumo de CSS do autor aplicados. Infelizmente, o Safari não inclui os detalhes na ordem de foco do teclado.

Se você incluir um <summary>, mas ele não for o primeiro elemento na <details>, o navegador ainda exibirá o resumo como deveria. Ele também não falhará se você incluir um link, uma etiqueta ou outro elemento interativo no resumo, mas os navegadores processarem o conteúdo interativo de maneira diferente. Por exemplo, se você incluir um link em um resumo, alguns navegadores adicionarão o resumo e o link à ordem de tabulação padrão, mas outros navegadores não se concentrarão no link por padrão. Se você clicar em um <label> aninhado em um <summary>, alguns navegadores darão foco para o controle de formulário associado. Outros navegadores vão focar o controle do formulário e abrir ou fechar a <details>.

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>) será mostrado ao usuário. O evento de alternância é disparado quando o elemento <details> é aberto ou fechado. É possível ouvir este evento usando addEventListener().

Se você quiser escrever um script para fechar os detalhes abertos quando o usuário abrir outros detalhes, remova o atributo aberto usando removeAttribute("open"):

Esse é o único exemplo que usa JavaScript. Você provavelmente não precisa de JavaScript, exceto para o recurso de fechar outros widgets de declaração abertos.

Lembre-se de que <details> e <summary> podem ser bastante estilosos e até mesmo usados para criar dicas de ferramentas. No entanto, se você quiser usar esses elementos semânticos para casos de uso em que a semântica nativa não é correspondente, mantenha a acessibilidade. A maior parte do HTML é acessível por padrão. Nosso trabalho como desenvolvedores é garantir que o conteúdo continue acessível.

Teste seu conhecimento

Teste seus conhecimentos sobre detalhes e resumo.

O <summary> precisa ser o primeiro filho de qual elemento?

<p>
Tente de novo.
<details>
Correto.
<fieldset>
Tente de novo.