Skip to content

Instantly share code, notes, and snippets.

@ardeshireshghi
Last active August 18, 2016 18:38
Show Gist options
  • Save ardeshireshghi/d03e3962697bef3a78b97e7bd6a0b5dd to your computer and use it in GitHub Desktop.
Save ardeshireshghi/d03e3962697bef3a78b97e7bd6a0b5dd to your computer and use it in GitHub Desktop.
Cool CSS3/JS modal
<!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">&#10005;</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