On cherche souvent la même chose : réduire le bruit visuel, garder la page lisible et laisser le lecteur déplier ce qui l’intéresse. En 2026, on obtient ce résultat proprement avec <details> et <summary>. Le navigateur fournit un widget natif. Ainsi, on évite les dépendances JavaScript, on simplifie le DOM et on améliore la robustesse.
Pourquoi ce pattern est la meilleure base en 2026
On gagne immédiatement sur quatre axes.
- Performance réelle
On supprime l’initialisation JS, les gestionnaires d’évènements et les recalculs inutiles. Le widget se comporte nativement. - Sémantique HTML correcte
On décrit une “divulgation” de contenu, pas une mise en scène. La spec définit clairementopenet le comportement attendu. - Accessibilité native
Le navigateur gère l’état ouvert/fermé et il le communique aux technologies d’assistance dans la plupart des cas. Cela réduit les erreurs d’implémentation « maison ». - Maintenance facile
On lit le HTML en une seconde. Ensuite, on itère avec CSS. Enfin, on n’ajoute du JS que si la valeur est claire.
Le modèle minimal, propre et “copier-coller”
On commence par la version la plus stable.
<details>
<summary>Lire la suite</summary>
<p>
Ce contenu reste masqué par défaut. On l’affiche en cliquant sur le résumé.
</p>
</details>
Code language: HTML, XML (xml)
- Quand
openest absent, on n’affiche que le<summary>. - Quand
openest présent, on affiche aussi le contenu.
<details open>
<summary>Replier</summary>
<p>Le contenu s’affiche dès le chargement.</p>
</details>
Code language: HTML, XML (xml)
Le composant “production” : style moderne, focus visible, sans hack
On veut généralement trois choses : un résumé cliquable clair, un indicateur d’état et un focus clavier impeccable. On garde le HTML simple.
HTML
<details class="disclosure">
<summary class="disclosure__summary">
<span class="disclosure__title">Lire la suite</span>
<span class="disclosure__chevron" aria-hidden="true"></span>
</summary>
<div class="disclosure__body">
<p>
On place ici un complément d’explications, une FAQ, ou une section “méthode”.
Le navigateur gère l’ouverture et la fermeture.
</p>
</div>
</details>
Code language: HTML, XML (xml)
CSS
.disclosure {
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 14px;
padding: 0.9rem 1rem;
}
.disclosure__summary {
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
/* On neutralise le marker natif, puis on crée un chevron. */
.disclosure__summary::-webkit-details-marker {
display: none;
}
.disclosure__summary::marker {
content: "";
}
.disclosure__title {
font-weight: 600;
line-height: 1.2;
}
.disclosure__chevron {
inline-size: 0.75rem;
block-size: 0.75rem;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(45deg);
transition: transform 180ms ease;
}
.disclosure[open] .disclosure__chevron {
transform: rotate(-135deg);
}
.disclosure__summary:focus-visible {
outline: 2px solid currentColor;
outline-offset: 4px;
}
.disclosure__body {
margin-top: 0.85rem;
}
Code language: CSS (css)
On peut styler le triangle via ::marker car <summary> se comporte comme un item de liste, comme le détaille web.dev.
Accordéon exclusif sans JavaScript
Quand on publie une FAQ, on veut souvent “un seul ouvert à la fois”. On peut le faire nativement avec l’attribut name sur <details>. Chrome for Developers et MDN décrivent ce comportement d’accordéon exclusif :
<details class="disclosure" name="faq">
<summary class="disclosure__summary">
<span class="disclosure__title">Question A</span>
<span class="disclosure__chevron" aria-hidden="true"></span>
</summary>
<div class="disclosure__body">
<p>Réponse A.</p>
</div>
</details>
<details class="disclosure" name="faq">
<summary class="disclosure__summary">
<span class="disclosure__title">Question B</span>
<span class="disclosure__chevron" aria-hidden="true"></span>
</summary>
<div class="disclosure__body">
<p>Réponse B.</p>
</div>
</details>
Code language: HTML, XML (xml)
Ensuite, quand on ouvre “Question B”, le navigateur replie “Question A” automatiquement.
Pour la compatibilité, on vérifie l’état réel via Can I use (notamment Safari et Firefox selon versions)
Animations modernes, sans wrapper inutile, avec ::details-content
Longtemps, animer proprement le contenu demandait un conteneur. Désormais, ::details-content cible la partie extensible sans toucher au <summary>. MDN Web Docs documente le pseudo-élément et propose un exemple de transition.
Objectif : une ouverture “douce” sans casser la performance
On évite les animations “height: auto” instables. Ensuite, on privilégie l’opacité et un léger déplacement. Enfin, on respecte prefers-reduced-motion.
@supports selector(details::details-content) {
details::details-content {
opacity: 0;
transform: translateY(-0.25rem);
content-visibility: hidden;
}
details[open]::details-content {
opacity: 1;
transform: translateY(0);
content-visibility: visible;
}
@supports (transition-behavior: allow-discrete) {
details::details-content {
transition-property: opacity, transform, content-visibility;
transition-duration: 180ms;
transition-timing-function: ease;
transition-behavior: allow-discrete;
}
}
@media (prefers-reduced-motion: reduce) {
details::details-content {
transition: none;
transform: none;
}
}
}
Code language: CSS (css)
transition-behavior encadre le démarrage des transitions sur des propriétés discrètes.
Améliorations JavaScript optionnelles et mesurées
On n’ajoute du JS que si l’expérience le justifie. Deux cas reviennent souvent.
Cas 1 : fermer au clic extérieur
C’est un choix UX, pas une obligation.
<script>
document.addEventListener('click', (event) => {
const openDetails = document.querySelectorAll('details[open]');
for (const details of openDetails) {
if (!details.contains(event.target)) {
details.removeAttribute('open');
}
}
});
</script>
Code language: HTML, XML (xml)
Cette version reste légère. Elle évite jQuery. Elle coûte un unique listener.
Cas 2 : analytics d’ouverture
On écoute toggle. On envoie un évènement de suivi.
<script>
document.addEventListener('toggle', (event) => {
const details = event.target;
if (!(details instanceof HTMLDetailsElement)) return;
// Exemple minimal : on remplace par l’outil analytics réel.
const isOpen = details.open;
const label = details.querySelector('summary')?.textContent?.trim() ?? 'details';
console.debug('details_toggle', { isOpen, label });
}, true);
</script>
Code language: HTML, XML (xml)
L’API HTMLDetailsElement.open reflète l’attribut open.
SEO et intentions de recherche : faire mieux qu’un “Lire la suite”
On obtient un vrai gain SEO quand on structure le contenu selon l’intention du lecteur.
Ce qui fonctionne bien
- On transforme le
<summary>en mini-question. - Ensuite, on place une réponse directe en première phrase.
- Puis, on développe avec des exemples, des critères, des pièges.
Ce format matche une intention “comment faire” et une intention “comparaison”. De plus, le contenu reste indexable, car il existe dans le HTML. Plusieurs ressources comme CSS Tricks soulignent l’usage fréquent des FAQ.
Exemples de <summary> orientés requêtes :
- “Comment créer un accordéon sans JavaScript ?”
- “Quelle différence entre
<details>et un toggle JS ?” - “Comment styliser l’icône de
<summary>?”
Pièges courants et solutions
1. Le résumé trop vague
“Cliquez ici” n’aide ni le lecteur ni le moteur. On préfère une phrase descriptive.
2. Le marker stylé de manière fragile
On cible ::marker quand possible. Ensuite, on masque ::-webkit-details-marker pour WebKit. web.dev et CSS-Tricks couvrent ces approches.
3. Les animations agressives
On évite les animations de hauteur complexes. Ensuite, on privilégie opacity et translation. Enfin, on respecte le “reduced motion”. MDN Web Docs fournit une base avec ::details-content.
Intégration WordPress : sans dette technique
On peut intégrer ce pattern sans plugin.
- On colle le HTML dans un bloc “HTML personnalisé”.
- Ensuite, on place le CSS dans “CSS additionnel”vou un fichier de thème.
- Enfin, on ajoute le JS uniquement si un besoin existe.
On gagne une implémentation plus propre qu’un toggle jQuery. On réduit aussi le risque de conflit avec d’autres scripts.
Conclusion : la référence pratique
En 2026, on construit un “show/hide” durable avec trois couches.
- HTML natif (
<details>/<summary>) pour la structure et le comportement. (MDN Web Docs) - CSS moderne pour l’apparence, le focus et le marker. (web.dev)
- JS optionnel uniquement pour des besoins produit mesurables.
Ce choix maximise la performance, réduit la complexité et améliore la maintenabilité.
Votre site mérite performance et fiabilité. Grâce à mon expérience, je vous aide à optimiser WordPress/WooCommerce pour des résultats visibles.