Skip to content

Instantly share code, notes, and snippets.

@k1sul1
Last active September 23, 2016 11:17
Show Gist options
  • Save k1sul1/f413e62525483093f182a2545ea7d985 to your computer and use it in GitHub Desktop.
Save k1sul1/f413e62525483093f182a2545ea7d985 to your computer and use it in GitHub Desktop.
VanillaJS css animated modals. http://jsbin.com/difozaxobo/
import {
runOnce
} from './runOnce.js';
export function openModal(element = undefined) {
const modalWrapper = element instanceof HTMLElement ? element : document.querySelector('.modal');
const actualModal = modalWrapper.children[0];
if (modalWrapper.classList.contains('transitionInProgress')) {
return false;
}
modalWrapper.classList.add('transitionInProgress');
modalWrapper.style.height = `${document.body.offsetHeight}px`;
modalWrapper.style.display = 'block';
const animation = new Promise(resolve => {
for (let i = 0; i <= 100; i++) {
setTimeout(() => {
const opacity = (i * 0.01).toFixed(2);
modalWrapper.style.opacity = opacity;
if (i === 100) {
resolve('animation complete');
}
}, i * 3);
}
});
animation.then(response => {
console.log(response);
actualModal.style.marginTop = `${window.scrollY + 50}px`;
actualModal.classList.add('visible');
runOnce(actualModal, 'transitionend', () => {
modalWrapper.classList.remove('transitionInProgress');
});
}, error => {
console.error('How did this happen?', error);
});
return true;
}
export function closeModal(event) {
const modalWrapper = event.target.closest('.modal');
const actualModal = modalWrapper.children[0];
console.log('trigger close');
if (modalWrapper.classList.contains('transitionInProgress')) {
return false;
}
actualModal.classList.remove('visible');
modalWrapper.classList.add('transitionInProgress');
runOnce(actualModal, 'transitionend', () => {
const animation = new Promise(resolve => {
for (let i = 100, timer = 0; i >= 0; i--, timer++) {
setTimeout(() => {
const opacity = (i * 0.01).toFixed(2);
modalWrapper.style.opacity = opacity;
if (i === 0) {
resolve('animation complete');
}
}, timer * 3);
}
});
animation.then(response => {
console.log(response);
modalWrapper.style.display = 'none';
modalWrapper.classList.remove('transitionInProgress');
}, error => {
console.error('how did this happen?', error);
});
});
event.preventDefault();
return true;
}
export function runOnce(target, type, listener) {
target.addEventListener(type, function fn(event) {
target.removeEventListener(type, fn);
listener(event);
});
}
import {
openModal,
closeModal
} from './modals.js';
const styles = document.createElement('style');
styles.innerHTML = `
.modal{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: none;
opacity: 0;
}
.modal__inner{
width: 60%;
min-height: 200px;
background: #fff;
color: #222;
padding: 15px 20px;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
transition: 0.3s cubic-bezier(0.770, 0.000, 0.175, 1.000);
transform: scale(0);
}
.modal__inner.visible{
transform: scale(1);
}
}
`;
const wrapper = document.createElement('div');
wrapper.classList.add('modal');
const modal = document.createElement('div');
modal.classList.add('modal__inner');
modal.textContent = 'Hello world!';
const modalClose = document.createElement('button');
modalClose.textContent = 'Close modal';
modalClose.addEventListener('click', closeModal);
const button = document.createElement('button');
button.textContent = 'Click me!';
button.addEventListener('click', openModal);
wrapper.appendChild(modal);
modal.appendChild(modalClose);
document.body.appendChild(wrapper);
document.body.appendChild(button);
document.head.appendChild(styles);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment