JavaScript
Article
By James Hibbard

Quick-Tip: Show Modal Popup after Time Delay

By James Hibbard

In the following quick tip, I’m going to show you how to open a modal window on a web page after a short time delay. This might be useful to highlight a particular call to action, such as signing up for a newsletter or for getting likes on Facebook. Some sites also use this technique to display advertising.

An untimely popup between racket and shuttle cock

But before continuing, take a second to ask yourself if this is something you really need to do. Whenever a site I’m browsing opens a modal without me having clicked on something, I almost always close it immediately and get annoyed that my attention was jerked away from whatever it was I was looking at. In my opinion such techniques can detract from the overall experience of a site and there are better ways to make visitors aware of your content.

A Basic Implementation

Still reading? Ok, I guess you’re set on doing this, so let’s get to it. For the impatient, there is a working demo at the end of the article.

For this quick tip I’ll use the Colorbox plugin to display the modal. Colorbox relies on jQuery, so you’ll have to add that to your page as well. Here’s a template.

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8 />
    <title>Delayed modal demo</title>
    <link rel="stylesheet" href="https://cdn.rawgit.com/jackmoore/colorbox/master/example1/colorbox.css" />
  </head>
  <body>

    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <script src="https://cdn.rawgit.com/jackmoore/colorbox/master/jquery.colorbox-min.js"></script>
    <script>
      <!-- Code here -->
    </script>
  </body>
</html>

Note that I’m using various CDNs to include the scripts here, but you could also install the dependencies using a package manager such as npm or bower.

Displaying the Modal

Normally, we would assign Colorbox to an HTML element and pass in any settings as key/value pairs inside an object:

$(selector).colorbox({
  key:value, 
  key:value
});

However, we want to call colorbox directly (without assigning it to anything), so the syntax is slightly different:

$.colorbox({
  key:value, 
  key:value
});

Colorbox has a bunch of options (many related to displaying images) which allow you to customize the modal. In the following example I am specifying its dimensions, giving it a class name (which allows me to style it using CSS) and passing it a string of HTML to display. You can find a full list of options on the page linked to above.

$.colorbox({
  html:"<h2>Call For a Free Quote</h2>",
  className: "cta",
  width: 350,
  height: 150
});

Then all that we need to do is use JavaScript’s setTimeout function to call this code after the required period of time has elapsed. setTimeout() is a native JavaScript function, which calls a function or executes a code snippet after a specified delay in milliseconds. If you’d like to get up to speed with the ins and outs of setTimeout(), then you can read this SitePoint tutorial.

setTimeout(function(){
  $.colorbox({
    html:"<h2>Call For a Free Quote</h2>",
    className: "cta",
    width: 350,
    height: 150
  });
}, 10000);

The popup will now open after your visitor has been browsing the site for ten seconds.

Accessibility Concerns

There are a number of accessibility concerns surrounding modal windows, for example: can keyboard users interact with them? Is the markup semantic? Are they easy to dismiss? You can find a more thorough discussion of the subject here: Making Modal Windows Better For Everyone.

Although, Colorbox comes with a lot of these features out of the box, there are still a couple of things we can improve.

Shifting Focus

When the modal opens, Colorbox shifts the focus to the window itself. This is good, but if we have any interactive elements in the modal (e.g. an <input> element) we could consider setting the focus to this instead. This will mean one less mouse click for mouse users and less button presses for those people using a keyboard. We can do this using JavaScript’s focus method.

We’ll also need to make use of the onComplete event that Colorbox fires, to ensure that our content has been loaded.

$.colorbox({
  ...
  onComplete: function(){ $("#myInput").focus(); }
});

Remembering where the user was previously

After the user has dismissed out popup, it is only polite to return them to where they were previously on the page. To do this, we need to keep track of the most recent element the user has interacted with and reset the focus to this element once the modal closes.

var lastFocus;

setTimeout(function(){
  lastFocus = document.activeElement;

  $.colorbox({
    ...
    onClosed: function(){ lastFocus.focus(); }

  });
}, 2000);

Displaying the Popup Once Every X Hours

For the sake of usability, it’s not a good idea to have the modal open every single time the user visits your site. Instead consider showing it once every X hours, or once every X days.

One way to do this would be to set a cookie once the modal has been shown, which expires after an allotted time. You can then check for the cookie’s presence on page load and act accordingly.

To do this, we will need a set of functions for handling cookies. I recommend js-cookie for this task.

Include it in your page after the Colobox library:

<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.3/js.cookie.min.js"></script>

By this point, it also makes sense to start moving the various pieces of functionality into their own functions.

var lastFocus;

function onPopupOpen(){
  $("#myInput").focus();
}

function onPopupClose(){
  Cookies.set('colorboxShown', 'yes', { expires: 1 });
  lastFocus.focus();
}

function displayPopup(){
  $.colorbox({
    html:"<h2>Call For a Free Quote</h2>",
    className: "cta",
    width: 350,
    height: 250,
    onComplete: onPopupOpen,
    onClosed: onPopupClose
  });
}

setTimeout(function(){
  var popupShown = Cookies.get('colorboxShown');

  if(popupShown){
    console.log("Cookie found. No action necessary");
  } else {
    lastFocus = document.activeElement;
    displayPopup();
  }
}, 2000);

Demo

And here’s the whole thing working on CodePen. Run the embed and the popup will open three seconds later. It’ll only show once every 24 hours, as it sets a cookie as demonstrated above. Saying that, I’ve added a Clear Cookies button so that you can run the demo multiple times. You can rerun the embed by clicking on the Rerun button in the bottom right corner.

See the Pen gwWpQX by SitePoint (@SitePoint) on CodePen.

Conclusion

In this quick tip I have demonstrated how to open a pop up once a user has been browsing your site for a specified time. I have also highlighted usability and accessibility concerns surrounding this approach.

If you have any remarks or questions, I’d love to hear them in the comments below. If you have any questions concerning the code, or are getting stuck implementing this on your own site, I would recommend that you post a question in the JavaScript category of SitePoint’s forums.

  • Omar Wraikat

    Thanks for the helpful tip!
    One question: could the localStorage been used instead of cookies? if yes, which is better to use between the two?

    • James Hibbard

      Thanks :) Sure localStorage could have been used, but as it stores data with no expiration date, you’d need to check if the allotted time period has elapsed manually.

  • Can someone tell me why my code is not working?

    var bar = $(‘.progress-bar’);
    var bar_width = $(this);

    function loadDaBars() {

    $(bar).each(function(index) {
    setTimeout(function() {
    bar_width = $(this).attr(‘aria-valuenow’);
    $(this).css({“width”: bar_width + ‘%’});
    }, index * 200);
    });
    }

    loadDaBars();

    • James Hibbard

      Can you provide a JSFiddle or other runnable example?

        • James Hibbard

          The immediate problem is that within the setTimeout, the variable bar_width is undefined.

          However, you are also querying the DOM and redefining the loadDaBars function every time the scroll event is triggered on window (which is often). This is almost certainly not what you want to be doing.

          The comments section of this post is a bad place to discuss things. Why not head to SitePoint forums, open an account and post your question in the JavaScript forum. Then you can ping me (@Pullo) and I’ll answer there.

          • Ok, I’ll try to use forums. However, I’ve already found solution.
            Thanks a lot.

  • This is quite possibly the most annoying thing websites have done since adverts with sound or popups.

    • James Hibbard

      Agree with you there. This post was just a write up of a forum thread though and that had over 90k hits, so it seems to be something people want to do. Might as well explain how to do it properly then.

  • One quick quesion. Can js-cookie be used to show to the user message about cookies policy? For example, it shows him a message about cookies, after he click the button “accept the policy” it doesn’t show him again.

  • I have a great tip on how to implement a delayed modal: DON’T!
    It’s irritating.

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.