From our sponsor: Ready to show your plugin skills? Enter the Penpot Plugins Contest (Nov 15-Dec 15) to win cash prizes!
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); } }
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
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!
Awsm.. 🙂
“Great work again! Always 3 steps ahead.”
does not work on my android fyi
Works on mine. What model/browser are you using?
Hi Mary Lou,
I really enjoyed this one. Thanks for putting it together.
Awesome awesome as always!
Call function for multiple dialog windows
(function() {
$(‘[data-dialog]’).each( function(){
var dlgtrigger = this,
somedialog = document.getElementById( dlgtrigger.getAttribute( ‘data-dialog’ ) ),
dlg = new DialogFx( somedialog );
dlgtrigger.addEventListener( ‘click’, dlg.toggle.bind(dlg) );
});
})();
If there are multiple buttons, what is needed to be changed?
You are awesome .
Awesome 🙂
How do I set to multiple dialogs in the same page? 🙁
Thanks, You are awesome!!
awesome, as usual.
Awesome! as ever
Top Work 🙂
Also, really great to see you have embraced BEM. You just increased your awesomeness even more 🙂 (that’s a whole lot of awesomeness btw)
How do i set the popup display first when open page?
Thanks
If there are multiple buttons, what is needed to be changed?
Hi, is this possible to load the dialog box without having trigger click? so when page is initially load the dialog box will appear.
Thanks much..
Same question
Multiple dialogues really sounds like awesome ……..inspired though this little things….great and thanks
why not work on a page that contains jquery?
oh funciona sim, perdão!
oh yes it works, forgiveness!*
Thanks for these dialogs! When implementing these, however, I ran into a problem. I tweaked the call to have multiple boxes using code almost identical to Samuel’s, but when I call this from a JS function instead of inside HTML, it takes two clicks of the trigger button to have the dialog pop up, then the dialog appears twice. Is this something I can easily tweak to fix?
Thanks!
Hi guys,
for multiple buttons/dialogs:
There is some problem with the code. Have u tried it??
Hey Pedro,
I’m also having an issue getting your code to work. Any ideas why?
I’m not sure.. It works fine for me. Tested here: http://tympanus.net/Development/DialogEffects/test.html
Dear Pedro Botelho,
You forgot to mention the following lines in the code above.
var dlgtrigger = document.querySelector( ‘[data-dialog]’ ),
somedialog = document.getElementById( dlgtrigger.getAttribute( ‘data-dialog’ ) ),
dlg = new DialogFx( somedialog );
This works on multiple windows, but i have an issue. I’ve added inside the code so i can stop a playing video when the modal is closed.
It works on the first element, but not on the rest.
onEndAnimation(this.el.querySelector('.dialog__content'), function () { classie.remove(self.el, 'dialog--close'); var video = $("#videoStop").attr("src"); //added $("#videoStop").attr("src", ""); //added $("#videoStop").attr("src", video); //added });
You are awesome! 🙂 Thanks, that fixed using multiple dialogs for me!
Great Tut. One of the best modal boxes tut i have ever encountered. Simple yet beautiful.
Would love to see more from you.
regards
Brilliant Tut, thanks
Nice, good work!
Has anyone had any luck implementing a fix for Safari, or is there simply not one? I seem to only be having issues with Safari on a PC, which no one uses anyways.
Brilliant, as always! Much appreciated 🙂
Good design. I’m finding it difficult implementing this in php. can you help.
Excellent demo, thanks for sharing!
For those who wants to use multiple dialogs in a single page, querySelectorAll() should be used instead of querySelector(), ie.
(function()
{
var dlgTrigger = document.querySelectorAll(‘[data-dialog]’);
var someDialog, dlg;
for (i = 0; i < dlgTrigger.length; i++)
{
someDialog = document.getElementById( dlgTrigger[i].getAttribute( 'data-dialog' ) );
dlg = new DialogFx(someDialog);
dlgTrigger[i].addEventListener( 'click', dlg.toggle.bind(dlg) );
}
})();
Thanks a lot ! This is exactly what need.
This demo is beautiful, well done and thanks for sharing ! 🙂
I love a lot of these modals. Wilma is my favorite. I never thought I’d say that.
Manoela, where do you get inspiration? Every your tutorial is amazing and your ideas are brilliant!
If I use one modal window for a few buttons on page, I have a problem.
When I trying to close window, window automatic opening soon
Recall Me – button in header
…
Recall Me – button in contact section
I use this code:
(function() {
var dlgTrigger = document.querySelectorAll(‘[data-dialog]’);
var someDialog, dlg;
for (i = 0; i < dlgTrigger.length; i++) {
someDialog = document.getElementById( dlgTrigger[i].getAttribute( 'data-dialog' ) );
dlg = new DialogFx(someDialog);
dlgTrigger[i].addEventListener( 'click', dlg.toggle.bind(dlg) );
}
})();
Is there any possibility to adapt for $(document).ready(function() ? please 🙂
Hi Mary Lou, very, very cool dialog effects you guys have going here, thanks for sharing!
I implemented the dialog into one localhost project and used it for showing that i use cookies, just for fun. I then also tried to use the same for showing if any form input was empty, and i keep getting ‘Uncaught TypeError: Cannot read property ‘querySelector’ of null’. I have appended the script to the end of the body, i load the markup for my dialog through $.post and then i use:
var dlg = new DialogFx(document.getElementById(‘cookie_dialog’));
dlg.toggle();
Error show here.
Any chance you guys know what is going on?
You need to make sure that every data-dialog=’myDialog’ attribute has a dialog div with the class ‘dialog’ and a data-dialog-close attribute somewhere. The ID of the div should match the data-dialog’s value.
If you look at the dialogFx.js file, there are querySelectors for the dialog__content, dialog__overlay classes and a data-dialog-close attribute, so make sure your dialog div has all of those things. The element that calls the dialog with the data-dialog=’x’ attribute must match the ID of the dialog you’re calling.
Is there an easy method to disable some functionality without ripping apart the dialogFx js file? For example, I want to disable the data-dialog-close functionality on click of the overlay, or outside the dialog. Is there an easy way to do that?
awesome plugin 🙂
BTW , can i use this plugin in codeigniter ? example after i login , then the dialog box appear says “Welcome” . ?
can anyone ?
Thanks in advance 🙂
i’m very new in programming .
I have a question, When I click the close button dialog box reopen automatically! how to solve it?
This code :
$( document ).ready(function() { var dlgTrigger = document.querySelectorAll('[data-dialog]'); var someDialog, dlg; for (i = 0; i < dlgTrigger.length; i++) { someDialog = document.getElementById( dlgTrigger[i].getAttribute( 'data-dialog' ) ); dlg = new DialogFx(someDialog); dlgTrigger[i].addEventListener( 'click', dlg.toggle.bind(dlg) ); } });
On the eventListener try to unbind and after bind the click. Cheers
seems to be pointer events have to beset explicitly. Adding this to css helped me
.dialog button[data-dialog-close]{
pointer-events: none;
}
.dialog–open button[data-dialog-close]{
pointer-events: auto;
}
This awesome design, thanks for share.. 🙂
Why did you use double underlines in class names? it’s not standard as far as i know. really interested to know xD
Hello. I do not speak English. I use a translator. Thank you for a very cool script modal windows. I have this problem, and I decided to write you a question. How to make so that you can open several of these modal windows on a single page? I made them with different IDs, and still runs only the first window, and the rest do not work.
how Can i use more than one dialog box in the same page !?
when i changing the ids it didn’t work !
Great job!!
Great work! Can anyone help me how to call modal box by js code (don’t need to click button)?
find it! 🙂
just add an action by js: dlg.toggle();
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
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!!
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!
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
With a few modifications this works great for WooCommerce messages/errors/notices (dialogs that aren’t triggered with a button but on page load)
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 toDialogFx.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
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.
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…………….
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.
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
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.
awesome plugin !!!!
I need to put a scroll in a few moments the text is big. I’ve tried some ways but isn’t worked. Any idea?
Thanks in advance.