Conteúdo recolhível com details e summary
Envolva o conteúdo em <details> e coloque um <summary> primeiro. O summary fica visível; todo o resto fica escondido até o usuário clicar nele:
Clique na pergunta para abrir, e de novo para fechar. O navegador adiciona o marcador triangular, torna o summary focável, o alterna com Enter ou Espaço e diz aos leitores de tela se ele está expandido ou recolhido. Nenhum JavaScript envolvido.
Se você deixar o <summary> de fora, o navegador mostra um rótulo padrão ("Detalhes" em português) no lugar.
Aberto por padrão
O atributo booleano open mostra o conteúdo desde o início. O navegador adiciona e remove open conforme o usuário alterna, então ele também é o gancho para estilizar:
A caixa aberta tem uma borda azul vinda de details[open]. Abra "Returns" e ela também fica azul; as duas podem ficar abertas ao mesmo tempo.
Acordeão: só um aberto por vez
Dê a vários elementos <details> o mesmo name e eles viram um grupo exclusivo: abrir um fecha os outros. Isso antes exigia JavaScript e hoje funciona só com o atributo nas versões atuais de Chrome, Edge, Firefox e Safari:
Abra a segunda pergunta e a primeira fecha. Remova os atributos name e elas voltam a abrir de forma independente. Um acordeão exclusivo esconde conteúdo que o usuário talvez queira comparar, então use quando as seções são alternativas, e <details> simples quando as pessoas podem querer várias abertas.
Estilizando o marcador
O triângulo é um marcador de lista no summary. list-style: none o remove (a regra ::-webkit-details-marker cobre o Safari), e um pseudo-elemento pode desenhar o seu próprio indicador:
O sinal de mais gira 45 graus e vira um X quando a seção abre. Mantenha um estilo de foco visível como o contorno :focus-visible daqui: depois que você remove o marcador padrão, o contorno de foco é o que quem usa teclado tem como referência.
O evento toggle e a propriedade open
O JavaScript pode ler e definir details.open, e o evento toggle dispara depois de cada mudança, seja ela causada por um clique, uma tecla ou um script:
"Expand all" define open nos dois, e o log mostra o último evento toggle. O evento não se propaga (não faz bubbling), então escute em cada elemento <details>, e não num pai.
O que vai num summary
Um summary contém texto, elementos inline ou um título, quando o título da seção faz parte da estrutura da página:
<details>
<summary><h3>Refund policy</h3></summary>
<p>...</p>
</details>
Evite links, botões e campos de formulário dentro de <summary>: o summary já é um controle, então um controle dentro dele é fácil de não ver ou de acionar sem querer, e os leitores de tela anunciam mal controles aninhados. Coloque o conteúdo interativo no corpo do <details>.
Erros comuns
- Montar uma alternância com uma
<div>e JavaScript.<details>já cuida dos cliques, das teclas e do estado para o leitor de tela. Quando você precisar mesmo de uma alternância personalizada, use um button comaria-expanded. - Colocar o
<summary>em outro lugar que não o primeiro. Ele precisa ser o primeiro filho de<details>. - Esconder o marcador sem colocar outro. Dê ao usuário algum sinal de que o summary abre, como o sinal de mais acima.
- Usar
displaypara esconder o conteúdo. Alterne oopen; um CSS que força o conteúdo a ficar visível ou escondido briga com o estado do navegador. - Grupos exclusivos para conteúdo que as pessoas comparam. Use
namesó quando faz sentido uma seção aberta por vez.
Perguntas frequentes
O que details e summary fazem no HTML?
<details> cria um widget de divulgação: uma seção que pode ser aberta e fechada. O seu primeiro filho, <summary>, é o rótulo sempre visível; clicar nele (ou apertar Enter ou Espaço quando ele tem o foco) mostra ou esconde todo o resto dentro de <details>.
Como deixar um details aberto por padrão?
Adicione o atributo booleano open: <details open>. O navegador adiciona e remove esse atributo conforme o usuário alterna, então o CSS pode estilizar details[open].
Como fazer um acordeão em que só uma seção fica aberta?
Dê a todos os <details> do grupo o mesmo atributo name, por exemplo name="faq". Abrir um fecha os outros desse grupo, sem JavaScript.
Como remover ou mudar a seta do summary?
Defina list-style: none no summary e adicione summary::-webkit-details-marker { display: none; } para o Safari. Depois desenhe o seu próprio indicador, por exemplo com summary::after, e mude-o com details[open] summary::after.
Dá para detectar quando um details abre?
Sim. Escute o evento toggle no elemento <details> e leia a sua propriedade open. Definir details.open = true no JavaScript o abre.