Last active
September 23, 2016 11:17
-
-
Save k1sul1/f413e62525483093f182a2545ea7d985 to your computer and use it in GitHub Desktop.
VanillaJS css animated modals. http://jsbin.com/difozaxobo/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function runOnce(target, type, listener) { | |
target.addEventListener(type, function fn(event) { | |
target.removeEventListener(type, fn); | |
listener(event); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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