Cliquez ici
Nulla consequat nec purus vel faucibus. Pellentesque sit amet lectus tincidunt, viverra ex vel, volutpat eros. Morbi vel turpis leo. Phasellus vehicula ipsum porta, ullamcorper nisl vitae, vehicula est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; In luctus at lorem posuere finibus. Donec vitae purus vitae turpis condimentum tincidunt in at tortor. Cras laoreet orci in erat tincidunt scelerisque. Maecenas viverra purus ex, et pulvinar massa ultricies sit amet. Aliquam erat volutpat. Phasellus eget metus nec diam suscipit malesuada in rhoncus metus.
<details>
<summary>Sommaire</summary>
<div class="contenu-details">
...
</div>
</details>
summary{
display:grid;
grid-template-columns: auto 1fr;
gap:1rem;
background-color:#ccc;
align-items:center;
padding:1rem;
cursor:pointer;
}
summary::before {
content:"";
height:.625rem;
width:.625rem;
pointer-events:none;
will-change:transform;
transform:translate3d(0,0,0) rotate(45deg);
transition:rotate 400ms;
border-top: 2px solid #555;
border-right: 2px solid #555;
border-top-right-radius: 2px;
}
details[open] summary::before {
rotate:90deg;
transition: rotate 200ms ease-in;
}
class Accordion {
constructor(el) {
this.el = el;
this.summary = el.querySelector('summary');
this.content = el.querySelector('.contenu-details');
this.animation = null;
this.isClosing = false;
this.isExpanding = false;
this.summary.addEventListener('click', (e) => this.onClick(e));
}
onClick(e) {
e.preventDefault();
this.el.style.overflow = 'hidden';
if (this.isClosing || !this.el.open) {
this.open();
} else if (this.isExpanding || this.el.open) {
this.shrink();
}
}
shrink() {
this.isClosing = true;
const startHeight = `${this.el.offsetHeight}px`;
const endHeight = `${this.summary.offsetHeight}px`;
if (this.animation) {
this.animation.cancel();
}
this.animation = this.el.animate({
height: [startHeight, endHeight]
}, {
duration: 400,
easing: 'ease-out'
});
this.animation.onfinish = () => this.onAnimationFinish(false);
this.animation.oncancel = () => this.isClosing = false;
}
open() {
this.el.style.height = `${this.el.offsetHeight}px`;
this.el.open = true;
window.requestAnimationFrame(() => this.expand());
}
expand() {
this.isExpanding = true;
const startHeight = `${this.el.offsetHeight}px`;
const endHeight = `${this.summary.offsetHeight + this.content.offsetHeight}px`;
if (this.animation) {
this.animation.cancel();
}
this.animation = this.el.animate({
height: [startHeight, endHeight]
}, {
duration: 400,
easing: 'ease-out'
});
this.animation.onfinish = () => this.onAnimationFinish(true);
this.animation.oncancel = () => this.isExpanding = false;
}
onAnimationFinish(open) {
this.el.open = open;
this.animation = null;
this.isClosing = false;
this.isExpanding = false;
this.el.style.height = this.el.style.overflow = '';
}
}
document.querySelectorAll('details').forEach((el) => {
new Accordion(el);
});