Hartley Brody

Adding Subtle Pop-ups to Your Website

It’s fairly common knowledge that website visitors hate pop-up windows. By definition, they interfere with what you’re doing and try to draw your attention to something else. In the early days of the internet, they were everywhere, but these days all major browsers block pop-up windows by default.

Now, site owners are switching to modal windows which usually don’t get caught by pop-up blockers since they use more complex javascript and CSS.

But if website visitors hate these intrusive windows so much, why do website owners still use them?

Because they work.


Elements that move around or suddenly appear on-screen are far better at grabbing attention since they don’t sit in so-called “banner blind spots“. These tend to convert traffic far better than standard calls-to-action do.

At HubSpot, we recently added two subscription forms to our blog to encourage people to subscribe via email. One was a standard sidebar widget that a lot of websites use, and one was a sliding modal window. After a week of testing, the modal window has been filled out twice as many times as the form in the sidebar widget. Clearly, it works.


It’s a delicate balance between not annoying your site’s visitors but still making sure they follow certain behaviors.

Depending on who you talk to, you’ll hear many different opinions about what’s “worth it” and what isn’t. Some say you should use full-screen pop-ups that block content until the visitor interacts with them, while others don’t want anything that disrupts users at all.

It was a debate that we had at HubSpot for many weeks before we finally found a comfortable balance. And that’s what I’m sharing with you today.

Check out the demo page to see it in action →

Warning: This post gets a little geeky, so a basic proficiency with CSS and jQuery is necessary to continue. Are you ready? Are you sure? Okay, let’s go…


The HTML

The first thing you’re going to need is the actual content of the modal window. This could be a simple image wrapped in a link, or a text link to another article, or a form that can be filled out directly in the window. This is totally up to you, depending on your site’s needs. For the purposes of this tutorial, I’ll be representing that content with

The actual HTML markup that you’re adding to your site is pretty simple. All you have to do is put your content inside a simple div that I’m calling “slider”:

<div id="slider">
    <!--call-to-action-->
</div>

The CSS

Now that we’ve prepared the content of our slider window, we want make sure that it’s hidden when the visitor first arrives on your website, so that we can make it appear later on. I decided to hide it in the lower right hand corner of the screen, just out of view, but you can move yours as necessary.

<style type="text/css">
    #slider{
        /*hide the window*/
        position:fixed;
        bottom:-200px;
        right:0px;
        /*set the size and background color*/
        height:195px; width:600px;
        background-color:#fff;
        /*add border*/
        border-top:1px solid #000;
        border-left:1px solid #000;
        /*add shadow*/
        -moz-box-shadow: 0px 0px 15px #888;
        -webkit-box-shadow: 0px 0px 15px #888;
        box-shadow: 0px 0px 15px #888;
    }
</style>

Notice how I’ve also added a border to the top and left sides of the slider, to make sure that it stands out against whatever content it’s covering. Mine doesn’t need bottom or right borders, since it will be tucked up against the edge of the visitor’s screen, but you may have to adjust this if you decide to move yours.

I’ve also added a subtle shadow around the slider so that it appears to be hovering over top of the rest of our website’s content.

The jQuery

This is where it gets geeky. There needs to be a “trigger” that causes the slider to appear, based on a visitor’s behavior. In this tutorial, I’m using the visitor’s scrolling behavior, since it indicates that the user is actively looking through our page.

To do this, we’re going to have the slider appear when the user has scrolled to the bottom of a blog post. If they’ve scrolled that far, then they probably just finished reading our content. This is the perfect time for a little nudge to make sure they don’t just click away from our site!

Our “trigger” needs to be an element that is at the bottom of every blog post. This could be a comment box, share buttons, etc. We’ll set this in a minute.

But first we have the isScrolledTo function, which checks to see how far our visitor has scrolled. If they’ve scrolled far enough that the trigger is in view, then this function returns true, which means it’s time to bring our slider window into view.

function isScrolledTo(elem) {
    var docViewTop = $(window).scrollTop(); //num of pixels hidden above current screen
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top; //num of pixels above the elem
    var elemBottom = elemTop + $(elem).height();
    return (elemTop <= docViewBottom); //if the bottom of the current viewing area is lower than the top of the trigger
}

Now that we can check to see if the trigger is in view, we need to run that check every time the scroll bar is moved using jQuery’s $(window).scroll() function.

If we find that the trigger has been reached, that means we’re ready to show our slider. We need to specify the animation that will bring the slider into view. Remember how we set the CSS to initially push the slider off the screen? Well, now we’ll use jQuery to update the CSS so that the slider comes nicely into view.

var trigger = $('#trigger-div');    //set the trigger
var reached = false;
$(window).scroll(function() {
    if(isScrolledTo(trigger)) {
        //slide CTA onto screen
        if(!reached){
            $('#slider').animate({
                bottom: 0
            }, "fast");
            reached = true;
        }
    }
    if (!isScrolledTo(trigger)) {
        //slide CTA off of screen
        if(reached){
            $('#slider').animate({
                bottom: -200
            }, "fast");
            reached = false;
        }
    }
});

The first line is where we specify our “trigger”. You’ll probably have to go digging through your website’s source code to find that element’s id. If you’re looking for a comment box and you see a line that looks like

, then you’d update that first line to say

var trigger = $('#comments');   //set the trigger

We’ve also added a reached variable, so that the animation doesn’t keep looping over and over, once the trigger has been reached.

NOTE: In this code, the slider appears when the trigger has been scrolled to, and then disappears again if the visitor scrolls back up and the trigger is no longer in view. If you want the slider to stay in place once the trigger has been reached – regardless of whether or not the user scrolls back up – simply remove lines 16 through 25 in the above snippet.

We’re almost ready to go! Make sure you wrap all of that jQuery inside some script tags and then make sure you load the jQuery library, otherwise none of this will work!

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

Everything

So, when it’s all put together, it should look something like this:

<div id="slider">
    <!--call-to-action-->
</div>
<style type="text/css">
    #slider{
        /*hide the window*/
        position:fixed;
        bottom:-200px;
        right:0px;
        height:195px; width:600px;
        background-color:#fff;
        /*add border*/
        border-top:1px solid #000;
        border-left:1px solid #000;
        /*add shadow*/
        -moz-box-shadow: 0px 0px 15px #888;
        -webkit-box-shadow: 0px 0px 15px #888;
        box-shadow: 0px 0px 15px #888;
    }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
    function isScrolledTo(elem) {
        var docViewTop = $(window).scrollTop(); //num of pixels hidden above current screen
        var docViewBottom = docViewTop + $(window).height();
        var elemTop = $(elem).offset().top; //num of pixels above the elem
        var elemBottom = elemTop + $(elem).height();
        return ((elemTop <= docViewBottom)); //if the bottom of the current viewing area is lower than the top of the trigger
    }
    var trigger = $('#trigger-div');    //set the trigger
    var reached = false;
    $(window).scroll(function() {
        if(isScrolledTo(trigger)) {
            //slide CTA onto screen
            if(!reached){
                $('#slider').animate({
                    bottom: 0
                }, "fast");
                reached = true;
            }
        }
        if (!isScrolledTo(trigger)) {
            //slide CTA off of screen
            if(reached){
                $('#slider').animate({
                    bottom: -200
                }, "fast");
                reached = false;
            }
        }
    });
});
</script>

You should paste this entire block of code into a code widget in your sidebar, so that it automatically appears on every page of your site.

Make sure you replace the <!--call-to-action--> with the actual content that you want your visitors to see, and update the var trigger = $(‘#trigger-div’); with whatever the ID of your trigger element is.

If you found this useful, send me a tweet!