JSFiddle - React, Tailwind, and code Playground
by TheCrossCarrier
HTML
<!-- Copy this structure and edit class names -->
<div class="block">
<div class="block__spoiler"> Click me</div>
<div class="block__content">
Content
</div>
</div>
<!------------------------------------------------>
CSS
/* Don't forget to edit class names (except .spoiler_opened) */
.block {
overflow: hidden;
transition: height 0.5s ease;
}
.block__spoiler {
position: relative;
width: fit-content;
cursor: pointer;
}
.block__spoiler::before {
content: "➤";
position: absolute;
right: -1.1em;
transform: rotate(180deg);
transition: transform 0.5s ease;
}
.spoiler_opened.block__spoiler::before {
transform: rotate(90deg);
}
.block__content {
display: none;
}
JavaScript
Spoiler('block', 'block__spoiler', 'block__content', 'flex')
function Spoiler(blockClass, buttonClass, contentClass,
contentDisplayType = 'block') {
document.addEventListener('DOMContentLoaded', () => {
'use strict'
const
block = document.querySelector(`.${blockClass}`),
button = document.querySelector(`.${buttonClass}`),
content = document.querySelector(`.${contentClass}`)
const blockInitialHeight = window.getComputedStyle(block, null)
.getPropertyValue('height')
// if block height: 'min-content' etc.
block.style.height = blockInitialHeight
let transitionEnd = () => {
block.removeEventListener('transitionend', transitionEnd)
content.style.display = 'none'
}
button.onclick = () => {
if (button.classList.contains('spoiler_opened')) {
block.style.height = blockInitialHeight
block.addEventListener('transitionend', transitionEnd)
}
else {
block.removeEventListener('transitionend', transitionEnd)
content.style.display = contentDisplayType
block.style.height = block.scrollHeight + 'px'
}
button.classList.toggle('spoiler_opened')
}
})
}