Referring to my previous video https://youtu.be/KajHhSl27Ro Some users asked about the method I use for “Reveal Blocks”. This video shows how I have done this. I now exclusively use the BEM naming conventions to keep code more consistent.
Referring to my previous video https://youtu.be/KajHhSl27Ro Some users asked about the method I use for “Reveal Blocks”. This video shows how I have done this. I now exclusively use the BEM naming conventions to keep code more consistent.
;((w,d)=>{
let revealContainers;
const blockClass = "reveal-block";
const triggerOpenElementClass = "reveal-block__trigger--open";
const triggerCloseElementClass = "reveal-block__trigger--close";
const triggerToggleElementClass = "reveal-block__trigger--toggle";
const triggerHoverEventClass = "reveal-block__trigger--hover";
const triggerMouseventClass = "reveal-block__trigger--click"; /* not really needed as Click is the default */
const openModifierClass = "reveal-block--open";
const contentElementClass = "reveal-block__content";
const init = ()=>{
revealContainers = d.querySelectorAll( '.' + blockClass);
revealContainers.forEach( blockEl => {
let trigger, event;
/* Toggle mode */
trigger = blockEl.querySelector('.' + triggerToggleElementClass);
if(trigger){
event = trigger.classList.contains(triggerHoverEventClass)? 'hover' : 'click';
switch(event){
case 'hover':
trigger.addEventListener('mouseenter', e => { e.preventDefault(); show(blockEl)});
trigger.addEventListener('mouseleave', e => { e.preventDefault(); hide(blockEl)})
break;
default:
trigger.addEventListener('click', e => { e.preventDefault(); toggleReveal(blockEl)})
break;
}
}
/* open mode */
trigger = blockEl.querySelector('.' + triggerOpenElementClass);
if(trigger){
event = trigger.classList.contains(triggerHoverEventClass)? 'hover' : 'click';
if(event === 'click'){
trigger.addEventListener('click', e => { e.preventDefault(); show(blockEl)});
}else{
trigger.addEventListener('mouseenter', e => { e.preventDefault(); show(blockEl)});
}
}
/* close mode */
trigger = blockEl.querySelector('.' + triggerCloseElementClass);
if(trigger){
event = trigger.classList.contains(triggerHoverEventClass)? 'hover' : 'click';
if(event === 'click'){
trigger.addEventListener('click', e => { e.preventDefault(); hide(blockEl)});
}else{
trigger.addEventListener('mouseenter', e => { e.preventDefault(); hide(blockEl)});
}
}
})
}
const show = el =>{
const blockEl = el.closest('.' + blockClass);
const contentEl = blockEl.querySelector('.' + contentElementClass);
blockEl.classList.add(openModifierClass);
blockEl.style.setProperty('--open-height', contentEl.scrollHeight + 'px');
}
const hide = el => {
const blockEl = el.closest('.' + blockClass);
blockEl.classList.remove(openModifierClass);
}
const toggleReveal = (element)=> {
const blockEl = element.closest('.' + blockClass);
if(blockEl.classList.contains(openModifierClass)){
hide(element);
}else{
show(element)
}
}
w.addEventListener('DOMContentLoaded', ()=>{
init();
})
})(window, document)
[class*="reveal-block__trigger"]{
cursor: pointer;
}
/* BLOCK */
.reveal-block {
--closed-height: 100px;
--open-height: 200px; /* initial, updated per element by JS */
--open-duration: 1s;
--close-duration: 0.5s;
/* Element */
&__content{
max-height: var(--closed-height);
overflow: hidden;
transition: max-height var(--close-duration);
/* Modifier */
&--fade{
mask-image: linear-gradient(to top, transparent 0, black var(--closed-height));
-webkit-mask-image: linear-gradient(to top, transparent 0, black 70px);
}
}
/* Modifier */
&--open{
/* Element */
.reveal-block__content{
max-height: var(--open-height);
transition: max-height var(--open-duration);
/* Modifier */
&--fade{
mask-size: 100% calc(100% + var(--closed-height));
-webkit-mask-size: 100% calc(100% + var(--closed-height));
}
}
}
}
Use this if you do not have an SCSSS preprocessor
[class*="reveal-block__trigger"]{
cursor: pointer;
}
/* BLOCK */
.reveal-block {
--closed-height: 100px;
--open-height: 200px; /* initial, updated per element by JS */
--open-duration: 1s;
--close-duration: 0.5s;
/* Element */
&__content{
max-height: var(--closed-height);
overflow: hidden;
transition: max-height var(--close-duration);
/* Modifier */
&--fade{
mask-image: linear-gradient(to top, transparent 0, black var(--closed-height));
-webkit-mask-image: linear-gradient(to top, transparent 0, black 70px);
}
}
/* Modifier */
&--open{
/* Element */
.reveal-block__content{
max-height: var(--open-height);
transition: max-height var(--open-duration);
/* Modifier */
&--fade{
mask-size: 100% calc(100% + var(--closed-height));
-webkit-mask-size: 100% calc(100% + var(--closed-height));
}
}
}
}