CSS Animated Modal Window

In this tutorial show how to make Animated CSS Dialog Box using HTML, JavaScript, SVG and CSS. It's very helpful for all developers who need to create awesome project using this animation dialog box framework.

Demo / Download

Author Ashwin Saxena
Hits
Created MARCH 25, 2015
License Open
Compatible browsers Chrome, Firefox, Safari

HTML Code



 <div class="button-wrap"><button data-dialog="somedialog" class="trigger">Open Dialog</button></div>


<div id="somedialog" class="dialog dialog--close">
					<div class="dialog__overlay"></div>
					<div class="dialog__content">
						<div class="morph-shape">
							<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 560 280" preserveAspectRatio="none">
								<rect x="3" y="3" fill="none" width="556" height="276"></rect>
							</svg>
						</div>
						<div class="dialog-inner">
							<h2><strong>Howdy</strong>, I'm a dialog box</h2>
							<div><button class="action" data-dialog-close="a">Close</button></div>
						</div>
					</div>
				</div> 

CSS Code



button {
	padding: 1em 2em;
	outline: none;
	font-weight: 600;
	border: none;
	color: #fff;
	background: #c94e50;
}

.dialog,
.dialog__overlay {
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
}

.dialog {
	position: fixed;
	display: -webkit-flex;
	display: flex;
	-webkit-align-items: center;
	align-items: center;
	-webkit-justify-content: center;
	justify-content: center;
	pointer-events: none;
}

.dialog__overlay {
	position: absolute;
	z-index: 1;
	background: rgba(55, 58, 71, 0.9);
	opacity: 0;
	-webkit-transition: opacity 0.3s;
	transition: opacity 0.3s;
	-webkit-backface-visibility: hidden;
}

.dialog--open .dialog__overlay {
	opacity: 1;
	pointer-events: auto;
}

.dialog__content {
	width: 50%;
	max-width: 560px;
	min-width: 290px;
	background: #fff;
	padding: 4em;
	text-align: center;
	position: relative;
	z-index: 5;
	opacity: 0;
}

.dialog--open .dialog__content {
	pointer-events: auto;
}

/* Content */
.dialog h2 {
	margin: 0;
	font-weight: 400;
	font-size: 2em;
	padding: 0 0 2em;
	margin: 0;
}



.dialog--open .dialog__overlay {
	-webkit-transition-duration: 0.8s;
	transition-duration: 0.8s;
}

.dialog--close .dialog__overlay {
	-webkit-transition-duration: 0.5s;
	transition-duration: 0.5s;
}

.dialog__content {
	padding: 0;
	background: transparent;
}

.dialog.dialog--open .dialog__content {
	opacity: 1;
}

.morph-shape {
	position: absolute;
	width: calc(100% + 4px);
	height: calc(100% + 4px);
	top: -2px;
	left: -2px;
	z-index: -1;
}

.morph-shape svg rect {
	stroke: #fff;
	stroke-width: 2px;
	stroke-dasharray: 1680;
}

.dialog--open .morph-shape svg rect {
	-webkit-animation: anim-dash 0.6s forwards;
	animation: anim-dash 0.6s forwards;
}

.dialog-inner {
	opacity: 0;
	background: #fff;
}

.dialog--open .dialog-inner {
	padding: 4em;
	opacity: 1;
	-webkit-transition: opacity 0.85s 0.35s;
	transition: opacity 0.85s 0.35s;
}

.dialog.dialog--open h2 {
	-webkit-animation: anim-elem-1 0.7s ease-out both;
	animation: anim-elem-1 0.7s ease-out both;
}

.dialog.dialog--open button {
	-webkit-animation: anim-elem-2 0.7s ease-out both;
	animation: anim-elem-2 0.7s ease-out both;
}

@keyframes anim-dash {
	0% {
		stroke-dashoffset: 1680;
	}
	100% {
		stroke-dashoffset: 0;
	}
}

@-webkit-keyframes anim-dash {
	0% {
		stroke-dashoffset: 1680;
	}
	100% {
		stroke-dashoffset: 0;
	}
}

/* Inner elements animations */

@-webkit-keyframes anim-elem-1 {
	0% { opacity: 0; -webkit-transform: translate3d(-150px, 0, 0); }
	100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); }
}

@keyframes anim-elem-1 {
	0% { opacity: 0; -webkit-transform: translate3d(-150px, 0, 0); transform: translate3d(-150px, 0, 0); }
	100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); }
}

@-webkit-keyframes anim-elem-2 {
	0% { opacity: 0; -webkit-transform: translate3d(150px, 0, 0); }
	100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); }
}

@keyframes anim-elem-2 {
	0% { opacity: 0; -webkit-transform: translate3d(150px, 0, 0); transform: translate3d(150px, 0, 0); }
	100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); }
}

JavaScript

/**
 * dialog box v0.1
 * Ashwin Saxena
 */
;
(function(window) {

    'use strict';

    var support = {
            animations: Modernizr.cssanimations
        },
        animEndEventNames = {
            'WebkitAnimation': 'webkitAnimationEnd',
            'OAnimation': 'oAnimationEnd',
            'msAnimation': 'MSAnimationEnd',
            'animation': 'animationend'
        },
        animEndEventName = animEndEventNames[Modernizr.prefixed('animation')],
        onEndAnimation = function(el, callback) {
            var onEndCallbackFn = function(ev) {
                if (support.animations) {
                    if (ev.target != this) return;
                    this.removeEventListener(animEndEventName, onEndCallbackFn);
                }
                if (callback && typeof callback === 'function') {
                    callback.call();
                }
            };
            if (support.animations) {
                el.addEventListener(animEndEventName, onEndCallbackFn);
            } else {
                onEndCallbackFn();
            }
        };

    function extend(a, b) {
        for (var key in b) {
            if (b.hasOwnProperty(key)) {
                a[key] = b[key];
            }
        }
        return a;
    }

    function DialogFx(el, options) {
        this.el = el;
        this.options = extend({}, this.options);
        extend(this.options, options);
        this.ctrlClose = this.el.querySelector('[data-dialog-close]');
        this.isOpen = false;
        this._initEvents();
    }

    DialogFx.prototype.options = {
        // callbacks
        onOpenDialog: function() {
            return false;
        },
        onCloseDialog: function() {
            return false;
        }
    }

    DialogFx.prototype._initEvents = function() {
        var self = this;

        // close action
        this.ctrlClose.addEventListener('click', this.toggle.bind(this));

        // esc key closes dialog
        document.addEventListener('keydown', function(ev) {
            var keyCode = ev.keyCode || ev.which;
            if (keyCode === 27 && self.isOpen) {
                self.toggle();
            }
        });

        this.el.querySelector('.dialog__overlay').addEventListener('click', this.toggle.bind(this));
    }

    DialogFx.prototype.toggle = function() {
        var self = this;
        if (this.isOpen) {
            classie.remove(this.el, 'dialog--open');
            classie.add(self.el, 'dialog--close');

            onEndAnimation(this.el.querySelector('.dialog__content'), function() {
                classie.remove(self.el, 'dialog--close');
            });

            // callback on close
            this.options.onCloseDialog(this);
        } else {
            classie.add(this.el, 'dialog--open');

            // callback on open
            this.options.onOpenDialog(this);
        }
        this.isOpen = !this.isOpen;
    };

    // add to global namespace
    window.DialogFx = DialogFx;

})(window);

/* call */


(function() {

    var dlgtrigger = document.querySelector('[data-dialog]'),
        somedialog = document.getElementById(dlgtrigger.getAttribute('data-dialog')),
        dlg = new DialogFx(somedialog);

    dlgtrigger.addEventListener('click', dlg.toggle.bind(dlg));

})();

Preview

CSS Animated Dialog Box

Advertisement

Google Matched Content...