Inspiration for Dialog Effects

A small collection of dialog effects using CSS animations for your inspiration. Some effects use SVG animations of morphing paths with the help of Snap.svg.

Dialog Effects

View demo Download source

Last year we posted some inspiration for modal window effects and today we’d like to share some fresh ideas with you. Styles and trends change and this calls for different effects that fit to a modern UI. This new set contains some subtle animations and also some more fancy SVG morphing techniques for dialogs.

Please note that this was tested in latest browser versions only.

Please also note that IE11 does not seem to support vieport units in calc() which we use in some of the animation transforms.

For the dialog we use the following markup:

<div id="somedialog" class="dialog">
	<div class="dialog__overlay"></div>
	<div class="dialog__content">
		<h2><strong>Howdy</strong>, I'm a dialog box</h2><
		div><button class="action" data-dialog-close>Close</button></div>
	</div>
</div>

Note that in the future we’ll be able to use the native <dialog> element. But currently support is still very weak, with IE, Firefox and Safari not supporting it.

As you can see, we have a main dialog wrap which contains the overlay and the dialog content. The basic style for the dialog is the following (vendor prefixes are omitted):

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

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

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

.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;
}

We use flexbox on the main dialog element in order to center the dialog content. The overlay will appear with a transition. Please note that pointer events don’t work for IE < 11.
Some effects have an additional division for the inner content in order to hide it initially and fade it in after an effect of the modal is finished. This makes sense for effects that scale/distort the dialog.

An example for an effect (Sandra) is the following:

.dialog.dialog--open .dialog__content,
.dialog.dialog--close .dialog__content {
	animation-duration: 0.3s;
	animation-fill-mode: forwards;
}

.dialog.dialog--open .dialog__content {
	animation-name: anim-open;
}

.dialog.dialog--close .dialog__content {
	animation-name: anim-close;
}

@keyframes anim-open {
	0% { opacity: 0; transform: scale3d(1.1, 1.1, 1); }
	100% { opacity: 1; transform: scale3d(1, 1, 1); }
}

@keyframes anim-close {
	0% { opacity: 1; }
	100% { opacity: 0; transform: scale3d(0.9, 0.9, 1); }
}

With adding the dialog--open and dialog--close classes, we can control the appearing of the dialog and its inner elements.

The script for the dialog is the following:

;( 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 );	

And we can call the dialog like this:

<script src="js/classie.js"></script>
<script src="js/dialogFx.js"></script>
<script>
	(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) );

	})();
</script>

…where our trigger button has the data-attribute data-dialog="somedialog".

For the SVG effects (except the line drawing of Wilma) we use Snap.svg to morph SVG paths. We add the SVG shape into a wrap right into the dialog content and then we define the path to morph to in data-morph-open.

(function() {

	var dlgtrigger = document.querySelector( '[data-dialog]' ),

		somedialog = document.getElementById( dlgtrigger.getAttribute( 'data-dialog' ) ),
		// svg..
		morphEl = somedialog.querySelector( '.morph-shape' ),
		s = Snap( morphEl.querySelector( 'svg' ) ),
		path = s.select( 'path' ),
		initialPath = path.attr('d'),
		steps = { 
			open : morphEl.getAttribute( 'data-morph-open' )
		},
		dlg = new DialogFx( somedialog, {
			onOpenDialog : function( instance ) {
				// reset path
				morphEl.querySelector( 'svg > path' ).setAttribute( 'd', initialPath );
				// animate path
				path.stop().animate( { 'path' : steps.open }, 300, mina.easein );
			}
		} );

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

})();

There seems to be some kind of stacking problem in Safari with the perspective effects. Read more about it here: Weird CSS Rotation Animation Glitch in Safari

We hope you enjoy these little effects and find them inspiring!

View demo Download source

Previous:
Next:

Tagged with:

Mary Lou (Manoela Ilic) is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

View all contributions by

Website: http://tympanus.net/

Related Articles

Feedback 66

  1. 1

    Hey .. Thanks for this .. its really awesome and works perfectly .. I was wondering if there is anyway i can make the box pop up on its own when the page has done loading .. instead of press a button first?

    Thank you

  2. 2

    Hi there,
    I’m desperately hoping I’ll get some help here.
    I want to put 2 different Dialog Effects on one page however the functions are obviously clashing because of their names.
    Do you have a solution?

    Thanks for some awesome code snippets though. You ROCK!!

  3. 3

    Hello! Could you help me with that?
    I have many AddToCart buttons on page, but they should open the same DIV I create using ajax. How can I get it?
    And how can I call the dialog opening without any trigger and button clicking?
    Thank you!

  4. 4

    Hello, thank you for this beautiful tut,
    my question is when i click on the ‘Close’ button i want to confirm if the button was click ‘close’?
    Sorry for my bad english

  5. 5

    With a few modifications this works great for WooCommerce messages/errors/notices (dialogs that aren’t triggered with a button but on page load)

  6. 6

    i use this script for few pop ups and i will help to everyone who want to make it too. Firt of all you need to bind click event to all your bttns:

    (function () {
    "use strict"
    var dlgtrigger = document.querySelectorAll('[data-dialog]')
    for(let i=0;i<dlgtrigger.length;i++){
    let somedialog = document.getElementById(dlgtrigger[i].getAttribute('data-dialog'));
    let dlg = new DialogFx(somedialog);
    dlgtrigger[i].addEventListener('click', dlg.toggle.bind(dlg));

    }
    })();

    After this, find in code of your script method DialogFx.prototype.toggle and change it to

    DialogFx.prototype.toggle = function(event) {
    var self = this;
    if( event.target.nodeName == 'DIV' ) {
    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 if(event.target.nodeName == 'A'){
    classie.add( this.el, 'dialog--open' );
    // callback on open
    this.options.onOpenDialog( this );
    }
    this.isOpen = !this.isOpen;
    };

    Pay attention, that you use <a href=""></a> for your trigger btn.
    Best regards, your comrad

    • 7

      Hi, thank you for your example, it works, almost. I just added in the example which i downloaded from this site one more button, popup opens when clicking on both, but i cant’t close it by clicking on ‘Close’ btn, it closes only by clicking outside.

  7. 8

    How can i use this in function means i want to use this is in onload() in body .
    when the page loading the dialog will appear.how can i set this with function .can you explain please…..
    it will help to my website and i want to use this functionality please……………..
    how can we use this effect in calling function means any where…………….

  8. 9

    How can i open the same popup a couple of times on one page? For example i have one popup and several buttons which open this popup.

  9. 10

    Thanks for this lovely dialog box, I have a problem with this when I want to use multiple button for one dialog. Dialog reopen several time when I want to close that.
    Please help me for fix this issue. I don’t know JS so please give me a full code for use.

    Thanks

    • 11

      Thanks for this awesome plugin,
      I did little changes in “Hello everyone from Russia” ‘s code and here you are:

      ———————————————————————-
      var dlgtrigger = document.querySelectorAll(‘[data-dialog]’),
      somedialog = document.getElementById(‘somedialog’),
      dlg = new DialogFx(somedialog);

      for(let i=0;i<dlgtrigger.length;i++){
      dlgtrigger[i].addEventListener('click', dlg.toggle.bind(dlg));
      }
      ———————————————————————–

      it doesn't need to create multiple DialogFx object for one dialog element (just move "new DialogFx" outside the for and problem is solved).
      and also there is no need to change in plugin itself.

Follow this discussion

Leave a Comment