Navigation

Techniques for creating modal windows

JavaScript, Web Design | Apr 3, 2012

Modal windows are most commonly described as anything that captures the user’s attention, and doesn’t allow them to return to the previous state until they interact with the object in question.

Now, that is a bit convoluted and I think it is better addressed with a few examples of websites that use the technique really well. One of those is Build It With Me which does it really well. If you head on over to their site and click on Sign Up, you will see a very literal example of when a modal box just works.

Often times when working with modals they are used to clean up user interfaces and try to enhance the user’s experience—but it is important to remember that sometimes they do the exact opposite. Consider annoying websites with too many JavaScript popups, or spam sites that actually confirm that you want to leave the site. That is ridiculous, and sites that do these things are absolutely a no-go, so make sure you know how to use modal dialogues before going forward with the implementation.

To give you a better example of how to do them right, we will talk theory—then afterwards we will get into examples to show you how to implement them into responsive design. So let’s jump right into some theory.

 

Modal theory

The basic theory of the user interface element for modals can be rather intertwined with other UI theorems that we will only tangentially touch on here. Basically, what we are looking at is a necessity that we have where we need a user to click on a specific section of the site, and to focus particularly on only that section until the completion of the task that section offers.

Now, this could be used for many different things such as user logins, form elements, download pages, or it could be to simply display a photo and look at that photo’s comments. Facebook uses this to help you focus on interaction when you click on a photo, but of course they allow you to cycle through the photos there as well. You can click on them, and then it takes away all the ability to interact with the main page until you either click outside of the modal box or click the “x” to return.

Basic modal theory though is very interesting, and really relies on those principles we just touched on. Let’s walk through a use-case so you can get a better idea of when and why to use one.

Let’s say that you run a website where the users can register and login to their storage that they have rented from you (online storage). Well, you as a company are pretty incredibly reliant on those users having a great flow from landing on your homepage to logging in. As that is one of the most important things your site offers, you would want the user to feel compelled to login and actually make it incredibly easy for them to do so.

Due to that you may have a large sign in link on your homepage, or an actual section for them to do so on the homepage, perhaps in the header. Though the problem with those are, that in the latter case, the user isn’t pointed to the login in anyway, and in the former the user isn’t compelled to make a decision.

Now, I don’t condone forcing users to do anything but gently nudging them is perfectly fine—and that is what I meant by ‘compelled’. So what you could do is a have a login link that pulls down a modal window with the login form right there on it. That way they never have to navigate away from the homepage and then navigate back (via the example we stated a moment ago), and they also are 100% aware of what they are supposed to do inside of the modal.

It is a very nice way to go about helping users understand what is happening and why it is happening. I have to say, I have used it myself for clients and the retention rate from homepage landing to login has increased by 35% in the past that I have seen. And those certainly aren’t numbers to shake a stick at; they are really valuable and clearly defined metrics on how much a simple modal window can increase retention and decrease bounce rate.

 

Coding a basic modal window

Let’s dive right into some code, but for now disregard what sort of modal type we are going to use and all the technicalities, and let’s just focus on the core basics. The HTML, the CSS, and the jQuery are what we are going to focus on for now.


The HTML Elements

There are two basic elements we need, a link to open the window and the window itself. The link is going to look like this:

<a href="#dialog" class="modalLink">Modal Window</a>

It has an href attribute that we’ll use later on, and a class of modalLink which we’ll use to identify it. The window will look like this:

<div id="modal">
  <div id="dialog" class="window">
    <div class="contents">
        <h3>Modal Window</h3>
        <p>Cras mattis consectetur purus sit amet fermentum. Nullam id dolor id nibh ultricies vehicula ut id elit. Donec sed odio dui. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p> 
        <a href="#" class="close">Close</a>
    </div>
  </div>
</div>

This code is a div with the class ‘window’, notice that it has the id of ‘dialog’ which matches the href of the link. Inside there is another div wrapping the contents of the window which includes a ‘close’ button. That’s wrapped in an outer div.

The outer div is just there to enclose our modal markup. Why do we need to enclose the markup? Because you’ll probably want more than one modal window, or at least the option to add more than one.

To set up more than one modal window first we need to add a second link:

<a href="#dialog" class="modalLink">Modal Window</a>
<a href="#dialogB" class="modalLink">Second Modal Window</a>

Next, we need to add a second window:

<div id="modal">

  <!-- First modal window -->    <div id="dialog" class="window">     <div class="contents">         <h3>Modal Window</h3>         <p>Cras mattis consectetur purus sit amet fermentum. Nullam id dolor id nibh ultricies vehicula ut id elit. Donec sed odio dui. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>          <a href="#" class="close">Close</a>     </div>  </div>
 <!-- Second modal window -->   <div id="dialogB" class="window">     <div class="contents">         <h3>Modal Window B</h3>         <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Vestibulum id ligula porta felis euismod semper. Sed posuere consectetur est at lobortis. Madio dui.</p>          <a href="#" class="close">Close</a>     </div>  </div>
</div>

Notice that both window divs are wrapped by the div with the id modal. Notice also that the id of the first modal window matches the href of the first link and that the id of the second modal window matches the href of the second link; that is how the links will target the correct window once we get to the jQuery.


The CSS elements

We need to style three elements of our modal windows, we’ll start with the simplest:

#modal .contents
{
   /* style the modal's contents, in this case we're just adding padding */
   padding:24px;
}

This code styles the div with the class ‘contents’ (that’s the one wrapping all of our content). You can style your content here, just as you would anywhere else on the page. I’d recommend at least a little padding, because typographic rules dictate that all content needs to breath.

Next, we’re going to style the blind. ‘Whoah, hold on. What’s a blind?’ I hear you cry. It’s very simple: a blind is the opposite of a mask, we’ll use it to blank out the rest of our page whilst the window is visible. And no, we haven’t created it in our markup, jQuery will do that for us. For now, we just need to provide a style for it so that it covers the whole of the window contents and most importantly, sits above the rest of the content on the z axis.

#blind
{
   /* position element so the z-index can be set */
   position:absolute;
   /* set z-index so the blind will cover all page content */
   z-index:9999;
   /* set the top, left, width and height so the blind covers the browser window */
   top:0;
   left:0;
   width:100%;
   height:100%;
   /* set the background to a suitably dark tone */
   background-color:#000000;
}

Lastly for the CSS, we need to style our window itself. We need to position the window above the blind. Then we need to size it with width and height properties.

Next, we need to set the margin-left to half the width multiplied by -1 (400 / 2 * -1 = -200) and the margin-top by half the height multiplied by -1 (248 / 2 * -1 = -124). Later on we’re going to use jQuery to position the element at top:50% and left:50%, because of these negative margins the window will appear to be centered regardless of the browser dimensions and we won’t have to try and position it based on the browser size.

Next we need to set the left and top properties to -1000px. Why would we want to do that? Well, we don’t want the modal window to be visible until the link is clicked. Another common technique is to set display:none in the CSS but recently that has started to be abused by spammers and it may now be flagged by search engines as a black hat technique, especially if you have a lot of keywords in your modal. By setting it to position well off screen instead, we achieve the same thing.

Finally we want to color the window a suitable page color, white in this case.

And just for good measure, why not also dip into CSS3 and throw on a box shadow just to really make it pop out of the screen — it’s not mission-critical and will be ignored if not supported.

#modal .window {
   /* position the element so that the z-index can be applied */
   position:absolute;
   /* Set the z-index to a number higher than the blind's z-index */
   z-index:10000;
   /* set the width and height of the window */
   width:400px;
   height:248px;
   /* give the window negative margins that match the width/2 and height/2 so it is centered */
   margin-left:-200px;
   margin-top:-124px;
   /* position the top left corner off stage so it can't be seen (instead of display:none;) */
   left:-1000px;
   top:-1000px;
   /* color the background so it shows up */
   background-color:#ffffff;
   /* throw on a CSS3 box shadow, because it's cool, and we can */
   box-shadow:4px 4px 80px #000;
   -webkit-box-shadow:4px 4px 80px #000;
   -moz-box-shadow:4px 4px 80px #000;
}


The jQuery

Finally we’re going to add some jQuery to power the modal. What we need it to do is capture clicks on the links; locate the corresponding window and then fade it in, creating a blind behind the window that will prevent clicks onto other content; and finally, a function to  close the modal that can be triggered by our close button or by clicking outside of the window.

First we need to run the script only when the document is ready

$(document).ready(function(){

Next, define a variable to hold a reference to the window

var activeWindow;

Then add a click handler to the links, that function will prevent the default link behaviour; identify the corresponding window from the href attribute of the link; assign it to the activeWindow variable; move the window to the center of the browser (remember the negative margins in the CSS? This is where they work their magic because all we need to set is 50% to get the center) and fade it in; create a new div with the id ‘blind’, fade that in and attach a click handler of its own that will call the closeModal() function.

$('a.modalLink').click(function(e){	
    e.preventDefault();
    var id = $(this).attr('href');
    activeWindow = $('.window#' + id)
        .css('opacity', '0')
        .css('top', '50%')
        .css('left', '50%')
        .fadeTo(500, 1);

    $('#modal')         .append('<div id="blind" />')         .find('#blind')         .css('opacity', '0')         .fadeTo(500, 0.8)         .click(function(e){             closeModal();         });
});

Next we need to add a click handler to the close buttons to call the same closeModal() function as the click on the blind.

$('a.close').click(function(e){
    e.preventDefault();
    closeModal();
});

Last but not least, we need to create the closeModal() function that will return us to our initial state. It needs to fade out the window and move it back to its starting position when the transition completes, and at the same time, fade out the blind and remove it from the DOM when its transition completes.

function closeModal() {
    activeWindow.fadeOut(250, function(){ $(this).css('top', '-1000px').css('left', '-1000px'); });
    $('#blind').fadeOut(250,	function(){	$(this).remove(); });
}

Don’t forget to close your $(document).ready handler!

});

For those who prefer to learn by copy and paste, here’s the full script:

// run when page is ready
$(document).ready(function(){

    // create variable to hold the current modal window     var activeWindow;
    $('a.modalLink').click(function(e){
        // cancel the default link behaviour         e.preventDefault();
        // find the href of the link that was clicked to use as an id         var id = $(this).attr('href');
        // assign the window with matching id to the activeWindow variable, move it to the center of the screen and fade in         activeWindow = $('.window#' + id)             .css('opacity', '0') // set to an initial 0 opacity             .css('top', '50%') // position vertically at 50%             .css('left', '50%') // position horizontally at 50%             .fadeTo(500, 1); // fade to an opacity of 1 (100%) over 500 milliseconds
        // create blind and fade in         $('#modal')             .append('<div id="blind" />') // create a <div> with an id of 'blind'             .find('#blind') // select the div we've just created             .css('opacity', '0') // set the initial opacity to 0             .fadeTo(500, 0.8) // fade in to an opacity of 0.8 (80%) over 500 milliseconds             .click(function(e){                 closeModal(); // close modal if someone clicks anywhere on the blind (outside of the window)             });
    });
    $('a.close').click(function(e){             // cancel default behaviour             e.preventDefault();
            // call the closeModal function passing this close button's window             closeModal();     });
    function closeModal()     {
        // fade out window and then move back to off screen when fade completes         activeWindow.fadeOut(250, function(){ $(this).css('top', '-1000px').css('left', '-1000px'); });
        // fade out blind and then remove it         $('#blind').fadeOut(250, function(){ $(this).remove(); });
    }
});

The key to this process is to separate the modal window into its three components: data (HTML), style (CSS) and functionality (jQuery). There are thousands of variations that you can use to build on this core technique and we’d love read about some of your experiences in the comments below.

Dain Miller is a freelance web designer and developer based out of Madison Wisconsin. He is mainly focused on building products in the online education space, and he has a passion for responsive design. You can follow him on twitter at @_dain.

What are the best examples of modal windows you’ve seen? What’s your favorite technique for creating them? Let us know in the comments!

Share this post
Comments (no login required)
  • http://twitter.com/omipit Yahya J Aifit

    PERTAMAX

  • Anonymous

    It’s ironic that the article is slamming the spam sites for use of modal boxes, but I’d hardly say the WDD’s use is more user-friendly. When you click on an article, you aren’t directed to the article immediately; instead you’re faced with a frustrating modal regarding something that you probably have absolutely no interest in. It slows down the loading of the page, involves an extra  click and feels spammy, it’s also highly hypocritical!
    The article itself was good though!

    • Anonymous

      I should say that I don’t think my post, which is aimed at helping newcomers and people interested in learning, actually reflects the intentionality or thoughts of WDD.  And as a latter note, the act of using modal boxes is literally using that which takes users attention away from the content and does so until they exit – so it can be hard to make it UX friendly.  Now I agree, and of course I think everyone could be doing this better (pretty much everyone), but hey – everyone is learning as they go.  I don’t think its hypocritical of me to write this though, as I am not the designer – developer – nor affiliated with the daily decision making of WDD in any way, but I really appreciate you bringing this up as it is important to state these things.  Before I finish I should also make sure I say I am really grateful for your comment on the article’s content, and hope I made no offense to you or anyone else in responding to these things.  :)

      • Anonymous

        I agree with you but I think modals should only be used when there is user interaction (eg clicking on a ‘login’ button or enlarging a photo on Facebook) and not when the user had no intention of seeing the content of the modal.
        I’m sorry I sounded a little rude, I didn’t realise who had written this! I do hope it’s something WDD rectify though, because it detracts from awesome content like this. Thanks a lot for responding though!

      • Anonymous

        I completely agree regarding proper use of such modals.  And no worries at all, didn’t come off rude – just very opinionated which is totally awesome.  I think that the WDD could implement some of these techniques, but ironically enough, I have gotten some amazing PSD’s that happened to pop up as modal windows as I was browsing around (in the WDD) so I really appreciate that modal sometimes.  Though I will admit, that is the exception not the rule.  

      • Anonymous

        I too thought it a bit ironic that I was greeted with a modal after clicking the link from my reader to come to the site to read about this article about modals. :)

        In addition, the reason I came was to see the ‘rest’ of the article, which appeared truncated in my reader. Oddly, it appears to be truncated here as well, as the article/post ends with an incomplete sentence. “Wrap the CSS in tags, and the jQuery in “

  • Anonymous

    Why not simply make the mask position: fixed and give it a width and height of 100%? Then you wouldn’t need to bother with most of the resize code nor about the user scrolling the mask off-screen.

    • Anonymous

      Good point, but we wanted to use a method that specified responsive design (focused on that rather).  So using a 100% and such wouldn’t really explain that as nicely as using this method in the code.  Speaking of efficiency, it would probably be best to indeed do it this way you mention – but in this case I thought this would be preferable to learn from.  

      • Anonymous

        That’s a pretty strange argument. It doesn’t get much more responsive than using percentages (ignoring media queries and min-/max-width for a second). For the sake of the tutorial you could say it actually shows the reader how to calculate the width and height of an element based on the viewport’s width and height, but that’s pretty far-fetched.

        You’re basically making the tutorial harder to understand for novice HTML/CSS writers and overlooking a pretty well-supported positioning attribute in favor of a slower, more intensive solution. So I don’t see what you mean by saying this is the preferable solution to learn from.

        I’m sorry and I realize I’m probably coming across as arrogant by calling you out like this, but using javascript for this is just subpar both for learning and real word code.

      • Anonymous

        No worries, I understand what you are saying.  I basically did it this way because it would entice more interest I thought.  Well, that and I still honestly believe it to be a better position to learn from.  For instance, when I see a thread or tutorial about something I didn’t know you could do in jQuery/JavaScript it is like, boom, fascination.  It fascinates me so I go and do some research, and I end up learning more about the topic and surrounding ones than I ever imagined.  Same goes for a lot of people I assume.  And so as opposed to using something -everyone- has seen such as a 100% set attribute where there is likely no fascination, I think we are getting a bit of added value here not using it.  I know this may seem like a mundane argument, but it is small things such as that, that I consider when writing articles that I want to entice and get people interested in learning.  I really see where you’re coming from, and you are probably right, but I just chose to not go that route – respectfully.  

  • Jeffrey Gardner

    Dain, one thing that is often overlooked is that the most basic way to do a modal is to simply use click events and set the display of the modal to “display:block”.

    • Anonymous

      Hey Jeffrey.  Good point, but I wanted to do something that gave everyone a bit more interest in the goings on of JavaScript/jQuery and hoped that it’d inspire them to learn more :) – There are indeed many simpler ways to do it.  

  • Anonymous

    Yep, Twitter Bootstrap has a lot of great functionality for JavaScript and jQuery built in.

  • Anonymous

    Perhaps in the future, I’d love to do one of those.  :)

  • Anonymous

    Indeed, I could have cached them all in the beginning – but I felt for the use of a tutorial it’d be nice to explain them out in this fashion.  Arguably it’d just add another layer of complication onto what is already a complicated system (for people learning).  That is why I chose to not cache everything.

  • http://www.dbgtechnologies.com.au/ Rhys Lloyd

    I am definitely interested to see how this could be done purely with CSS3. All the animation and effects are easily achieved, but “opening” the modal dialog I’m unsure of how it could be done.

    I also read about caching in the comments; this is something I am yet to explore – would it be possible to write a tutorial about jQuery caching as an extension to this article?

  • Anonymous

    Great point.  I will take that into account next time.  Thanks!

  • Anonymous

     Sorry about that! That was an oversight on our part. We’ve changed the image now, but thanks for posting a link to your excellent blog post.

  • Anonymous

    Thank you for bringing this to our attention. You’re absolutely right that the code used in this article was too close to queness’ code.

    Webdesignerdepot is here to inspire, engage and educate designers and developers, the last thing we’d ever want to do is republish someone else’s work. Consequently we’ve rewritten the code above to ensure that it is original, we hope you’ll agree that this revision is as instructive as the first version.

    It just goes to show, on the web, there are dozens of unique approaches to solving the same problems!