Last active
August 18, 2016 18:38
-
-
Save ardeshireshghi/d03e3962697bef3a78b97e7bd6a0b5dd to your computer and use it in GitHub Desktop.
Cool CSS3/JS modal
This file contains 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title></title> | |
<link href='https://fonts.googleapis.com/css?family=Roboto:400,300,700' rel='stylesheet' type='text/css'> | |
<link href='https://fonts.googleapis.com/css?family=Raleway:400,700,500' rel='stylesheet' type='text/css'> | |
<style type="text/css"> | |
html { | |
height: 100%; | |
position: relative; | |
font-size: 1em; | |
} | |
body { | |
margin: 0; | |
padding: 0; | |
position: relative; | |
min-height: 100%; | |
font-family: 'Roboto', sans-serif; | |
background-color: #f6f6f6; | |
font-weight: 300; | |
} | |
.modal-container { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
width: 100%; | |
text-align: center; | |
transform: translateX(-50%) translateY(-50%); | |
height: 100vh; | |
} | |
[data-modal="cool"] { | |
text-decoration: none; | |
color: white; | |
background-color: #c0392b; | |
padding: 20px 60px; | |
width: 260px; | |
box-sizing: border-box; | |
font-size: 24px; | |
display: inline-block; | |
position: relative; | |
line-height: 24px; | |
top: 50%; | |
transform: translateY(0) translateX(0) translateZ(0px); | |
} | |
[data-modal="cool"] .cool-modal__content { | |
opacity: 0; | |
visibility: hidden; | |
position: absolute; | |
z-index: 10; | |
transform: translateY(30px) translateZ(0px); | |
-webkit-transition: opacity .5s ease .1s, transform .5s ease; | |
transition: opacity .5s ease .1s, transform .5s ease; | |
font-size: 1em; | |
height: 100%; | |
} | |
[data-modal="cool"]::before { | |
position: absolute; | |
content: ' '; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: #c0392b; | |
opacity: 0; | |
transform: scale(1) translateZ(0px); | |
transition: transform 0.5s cubic-bezier(1, 0.02, 0.24, 0.68); | |
} | |
[data-modal="cool"].cool-modal--show { | |
z-index: 100; | |
} | |
[data-modal="cool"].cool-modal--show::before { | |
opacity: 1; | |
} | |
[data-modal="cool"].cool-modal--fullscreen { | |
position: fixed; | |
left: 0; | |
top: 0; | |
transform: translateX(0px) translateY(0px) translateZ(0px); | |
width: 100%; | |
height: 100%; | |
padding: 0; | |
} | |
[data-modal="cool"].cool-modal--opened::before { | |
width: 100%; | |
height: 100%; | |
transform: scale(20) translateZ(0px); | |
transform-origin: center; | |
} | |
[data-modal="cool"] .cool-modal__content.show { | |
opacity: 1; | |
transform: translateY(0px) translateZ(0px); | |
position: relative; | |
visibility: visible; | |
height: 100%; | |
-webkit-transition: opacity .5s ease, transform .5s ease .1s; | |
transition: opacity .5s ease, transform .5s ease .1s; | |
} | |
.cool-modal__content .cool-modal__close { | |
position: absolute; | |
right: 40px; | |
top: 40px; | |
cursor: pointer; | |
font-size: 2rem; | |
} | |
.cool-modal__content .cool-modal__content__inner { | |
top: 50%; | |
transform: translateY(-50%) translateZ(0px); | |
position: relative; | |
margin: 0 auto; | |
max-width: 1200px; | |
text-align: center; | |
padding: 20px; | |
box-sizing: border-box; | |
} | |
</style> | |
<style type="text/css"> | |
.custom-content p { | |
font-size: .8em; | |
} | |
.custom-content h3 { | |
font-size: 1.6rem; | |
font-family: 'Raleway', sans-serif; | |
text-align: center; | |
} | |
@media screen and (min-width: 769px) { | |
.custom-content p { | |
font-size: 1em; | |
} | |
.custom-content h3 { | |
font-size: 2.4rem; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="modal-container"></div> | |
<script type="text/template" data-cool-modal-template> | |
<a href="#" data-modal="cool"> | |
<div class="cool-modal__content"> | |
<div class="cool-modal__close cool-modal__close--js">✕</div> | |
<div class="cool-modal__content__inner cool-modal__content__inner--js"> | |
{{modal-content}} | |
</div> | |
</div> | |
{{modal-btnText}} | |
</a> | |
</script> | |
<script type="text/javascript"> | |
var CoolModal = (function(document, window) { | |
function CoolModal(options) { | |
var modalElSelector = '[data-modal="cool"]'; | |
var modalEnabled = false; | |
var modalContainerEl = options.containerEl || body; | |
var body = document.body; | |
var modalElement; | |
function addEvent(type, el, callback, context) { | |
callback = (context) ? callback.bind(context) : callback; | |
if (el.addEventListener) { | |
el.addEventListener(type, callback, false); | |
} else if (el.attachEvent) { | |
el.attachEvent('on' + type, callback); | |
} else { | |
el['on' + type] = callback; | |
} | |
} | |
function removeEvent(type, el, callback) { | |
if (el.addEventListener) { | |
el.removeEventListener(type, callback, false); | |
} else if (el.attachEvent) { | |
el.detachEvent('on' + type, callback); | |
} else { | |
el['on' + type] = null; | |
} | |
} | |
function isArray(canBeArray) { | |
if (Array.isArray) { | |
return Array.isArray(canBeArray); | |
} else { | |
return (Object.prototype.toString.call(canBeArray) === "[object Array]"); | |
} | |
} | |
function onModalTransitionFinished(e) { | |
var finishedtransitions = (this.dataset) | |
? this.dataset.finishedtransitions | |
: parseInt(this.getAttribute('finishedtransitions'), 10); | |
finishedtransitions++; | |
if (finishedtransitions === 1) { | |
removeEvent('transitionend', this, onModalTransitionFinished); | |
if (this.classList.contains('cool-modal--opened')) { | |
setFullScreenMode(this); | |
} else { | |
hideModal(this); | |
} | |
} | |
} | |
function setFullScreenMode(el) { | |
el.classList.add('cool-modal--fullscreen'); | |
if (modalContainerEl !== body) { | |
body.appendChild(el); | |
} | |
el.offsetHeight; | |
el.querySelector('.cool-modal__content').classList.add('show'); | |
} | |
function hideModal(el) { | |
el.classList.remove('cool-modal--show'); | |
body.style.overflow = 'auto'; | |
} | |
function checkModalElClicked(e) { | |
body.style.overflow = 'hidden'; | |
this.classList.add('cool-modal--show'); | |
this.classList.add('cool-modal--opened'); | |
// Finished transitions reset | |
setElFinishedTransitions(this, 0); | |
addEvent('transitionend', this, onModalTransitionFinished); | |
} | |
function setElFinishedTransitions(el, value) { | |
if (el.dataset) { | |
el.dataset.finishedtransitions = value; | |
} else { | |
el.setAttribute('finishedtransitions', value); | |
} | |
} | |
function onModalCloseClicked(e) { | |
e.stopPropagation(); | |
// Finished transitions reset | |
setElFinishedTransitions(modalElement, 0); | |
if (modalContainerEl !== body) { | |
modalContainerEl.appendChild(modalElement); | |
} | |
addEvent('transitionend', modalElement, onModalTransitionFinished); | |
modalElement.classList.remove('cool-modal--fullscreen'); | |
modalElement.querySelector('.cool-modal__content').classList.remove('show'); | |
// Always helps | |
modalElement.offsetHeight; | |
modalElement.classList.remove('cool-modal--opened'); | |
} | |
function createModalEl() { | |
var btnTemplateEl = document.querySelector('[data-cool-modal-template]'); | |
var btnTemplateHtml = btnTemplateEl.innerHTML; | |
var modalEl; | |
// Interpolate template | |
['content', 'btnText'].forEach(function(property) { | |
btnTemplateHtml = btnTemplateHtml.replace('{{modal-' + property + '}}', options[property]); | |
}); | |
var tempEl = document.createElement('div'); | |
tempEl.innerHTML = btnTemplateHtml; | |
modalEl = tempEl.children[0]; | |
// Optional color | |
if (options.bgColor) { | |
modalEl.style.backgroundColor = options.bgColor; | |
} | |
if (options.color) { | |
modalEl.style.color = options.color; | |
} | |
return modalEl; | |
} | |
function prepareStyleAndRender() { | |
// Style changes for background color | |
if (options.bgColor) { | |
setModalBgColor(); | |
} | |
// Render | |
modalContainerEl.appendChild(modalElement) | |
} | |
function setModalBgColor() { | |
var style = document.createElement('style'); | |
var rule = modalElSelector + '::before{background-color:' + options.bgColor + '!important;}'; | |
var sheet; | |
// Add style | |
document.head.insertBefore(style, document.head.lastChild); | |
// Grab the stylesheet object | |
sheet = style.sheet; | |
// Use addRule or insertRule to inject styles | |
sheet.insertRule(rule, 0); | |
} | |
function updateContent(html) { | |
modalElement.querySelector('.cool-modal__content__inner--js').innerHTML = html; | |
} | |
function setEventListeners() { | |
addEvent('click', modalElement.querySelector('.cool-modal__close--js'), onModalCloseClicked); | |
addEvent('click', modalElement, checkModalElClicked); | |
} | |
function removeEventListeners() { | |
removeEvent('click', modalElement, checkModalElClicked); | |
removeEvent('click', modalElement.querySelector('.cool-modal__close--js'), onModalCloseClicked); | |
} | |
function disableModal() { | |
removeEventListeners(); | |
modalElement.classList.remove('cool-modal--opened'); | |
modalElement.classList.remove('cool-modal--fullscreen'); | |
body.style.overflow = 'auto'; | |
modalEnabled = false; | |
} | |
function init() { | |
if (modalEnabled) { | |
return; | |
} | |
if (!modalElement) { | |
modalElement = createModalEl(); | |
} | |
prepareStyleAndRender(); | |
setEventListeners(); | |
modalEnabled = true; | |
} | |
// Initial start | |
init(); | |
var modal = { | |
html: updateContent, | |
disable: disableModal, | |
enable: init, | |
getModalEl: function() { | |
return modalElement; | |
} | |
}; | |
return modal; | |
} | |
return CoolModal; | |
})(document, window); | |
</script> | |
<script type="text/javascript"> | |
var coolModal = CoolModal({ | |
btnText: 'Cool Modal', | |
bgColor: '#df4050', | |
containerEl: document.querySelector('.modal-container'), | |
content: '<div class="custom-content"><h3>Welcome to the new generation of modals</h3><p>This is a very simple modal module which makes use of CSS3 and a little javascript</p></div>' | |
}); | |
coolModal.html('haha'); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment