Perma-Closing Message Boxes with JavaScript + CSS

Published April 2, 2008 by CSS Newbies.

message box

Earlier this week I talked a bit about message boxes – how to style them and position them on your page to get them noticed. But a message that pops up every single time your website is loaded could get annoying. It’d be useful to give your users the ability to close those messages. For that, we’ll turn to our friend JavaScript.

We’ll start by building our message box in XHTML. Mine looks like this:

<div id="message-1" class="msgbox">
	<a href="#" id="close" title="Close This">X</a>
	<p>My uber-important message goes here!</p>
</div>

I’ve made a div with both an ID and a class. This will come in handy later when we need to reference our object in our JavaScript. Inside, I put an anchor tag with a class of “close.” This will become my close button later. And then I simply added a paragraph to hold my message.

Next up, we’ll want to style that message box. You can make it look pretty much however you want, and Woork has a nice article on styling message boxes, if you’re interested in discovering alternative styles. For my message box, I wrote this:

.msgbox {
	position: absolute;
	top: 15px;
	right: 20px;
	width: 20em;
	background-color: #b00;
	border: 1px solid #333;
	color: #fff;
	font-weight: bold; }
.msgbox p {
	margin: 0;
	padding: 5px 10px; }
.msgbox a.close {
	float: right;
	text-decoration: none;
	font-weight: bold;
	color: #333;
	background-color: #fff;
	border-left: 1px solid #333;
	border-bottom: 1px solid #333;
	padding: 0 4px;
	margin-left: 5px; }

Three rules are at play here. First, I’m styling the message box itself, using the class I gave it. I’m absolutely positioning the element and giving it a width. I’m also giving it a red background, bolding the text inside and turning it white, and applying a border. Then I’m applying a bit of styling to the paragraph inside to push it away from the side of the box.

Why didn’t I apply that padding to the message box itself? Because of the “close” link. I wanted to be able to float it to the right of the box and give it some styles to make it look more like a “close” button. After all of that CSS, this is what I have:

example message box

But so far, we just have a message box. That close button doesn’t do much of anything. For the rest, we’ll turn to JavaScript. All we need is a little function like this:

function closeBox(toClose) {
	document.getElementById(toClose).style.display = "none";
}

This function takes a single argument (toClose) which tells it the ID of the element we want to make disappear. We supply argument when we call the JavaScript. In this case, because we want it to happen when someone clicks our close box, we’d add it to our XHTML like this:

<a href="#" class="close" 
onclick="closeBox('message-1'); return false;" 
title="Close This">X</a>

We’ve added the “onclick” attribute to our “close” link tomake it fire a bit of JavaScript when the element is clicked. We’re telling it to call our closeBox function that we just wrote, and we’re giving it the ID of the message box we want to close. The “return false” part basically tells it to stop (that is, not to actually go to our specified href afterwards).

That’s all we need to create a message box that closes! However, if your users close the box and then refresh the page, the message box comes right back. What if we want it to close permanently? For that, we’ll need some more fancy JavaScript, because we’ll need to make use of cookies.

The cookie will act as a check that we can refer back to. When the user closes the message box, we’ll set a cookie. Then, when they come back to the page, we’ll check to see if the cookie is set. If there’s no cookie, we’ll show them the message. If there is a cookie, we’ll keep the message box hidden.

First, we’ll make a small change to our CSS:

.msgbox {
	display: none; /* Start out hidden. */
	position: absolute;
	top: 15px;
	right: 20px;
	width: 20em;
	background-color: #b00;
	border: 1px solid #333;
	color: #fff;
	font-weight: bold; }

All we’re doing is adding a “display: none” to the top of the element. By default, we don’t want our message box to show up. Instead, we’ll use JavaScript to display it if we want to see it. Why? It’s a usability thing: this way, if a user doesn’t have JavaScript enabled, they don’t see the message box. That may seem like a bad thing, but consider the alternative: if we didn’t set this rule, then anyone without JavaScript couldn’t get rid of your message box. And depending on its placement, that could be a big usability problem.

So now we need two extra functions in our JavaScript: one to set the cookie when we close the box, and another to check to see if the cookie exists when the user comes back. Our JavaScript now looks like this:

function closeBox(toClose) {
	document.getElementById(toClose).style.display = "none";
	setCookie(toClose, "closed", 365);
}
function setCookie(cName, value, expiredays) {
	var expDate = new Date();
	expDate.setDate(expDate.getDate()+expiredays);
	document.cookie=cName + "=" + escape(value) + 
	";expires=" + expDate.toGMTString();
}
function loadMsg(msgClass) {
	msg = document.getElementsByTagName("div");
	for (i=0; i<msg.length; i++) {
		if(msg[i].className == msgClass) {
			if(document.cookie.indexOf(msg[i].id) == -1) {
				msg[i].style.display = "block";
			}
		}
	}
}

First off, we modified our closeBox() function to make a call to the setCookie() function after it’s hidden the message box.

Next comes the setCookie() function. It takes three arguments: the name of the cookie, the value to be set, and how long the cookie should last before it expires (in days). We could have hard-coded some of this stuff to save time and space, but this way you can reuse this same function to set cookies all over your site – not just for this purpose.

Also, note that we’re using the toClose variable for our cookie name in setCookie()… which you might also remember is the ID of the message box itself. This is a useful trick, because this means you could theoretically have multiple message boxes with different IDs (all with the same .msgbox class) on your page, and you could open and close them separately, because each of their states would be set in a unique cookie.

Next comes the loadMsg() function. It takes one argument: msgClass. This variable represents the class you’ve set on all your message boxes. Our loadMsg() function cycles through all the <div> tags on your website and checks to see if they have the “msgClass” class set (whatever that happens to be… in my document, that was “msgbox”). If it finds such a div, it checks to see if it can find a cookie with a name that matches the ID set on that div – in our example it would be looking for “message-1.” If it doesn’t find a match (meaning the user hasn’t closed the box), then it sets that div to “display: block,” meaning it will show up normally. Otherwise, the message box stays hidden.

Now, all we need to do is ensure the loadMsg() function runs when the page first loads. To do that, I just modified my body tag like so:

<body onload="loadMsg('msgbox');">

The “onload” attribute fires when the page has finished loading, and it will call the loadMsg() function for us, displaying our message boxes as needed. And that’s all there is to it! You can see a functioning example here.

Now, I did want to mention a couple of things before you try this on your own:

  • I’ve built this example specifically to make it work with multiple message boxes. Otherwise, it would have been easier and faster to reference our message box by its ID in our loadMsg() function.
  • This obviously only works if your users have JavaScript and cookies enabled. If they have JavaScript turned off, they won’t see a message box. If they have cookies turned off, they won’t be able to get rid of your message box. And I don’t know of a good way around this usability problem. That’s just the way the cookie crumbles.
  • You could achieve this same functionality in about half the space using a JavaScript framework. I have nothing against frameworks generally, but I do have something against forcing your users to download 50KB+ of JavaScript if you’re only going to use 1KB (or less) of it. For some things, frameworks make sense. For others, it’s better to just write it by hand.

But enough from me… I want to hear what you have to say about this technique. Leave me a comment!

28 Responses

  1. Pingback: javascript

  2. Pingback: Valontuoja » Blog Archive » Kaoottinen linkkidumppi

  3. Phil (reply)

    This helped me to embed my twitter status updates on my blog. Such a long time I’ve been trying to figure out how to do this in a convenient way for both the user and me. It looks great with some modifications! :)
    Awesome!

  4. Pingback: javascript for time

  5. Pingback: jQuery-Based Popout Ad: Part 3 | Castup

    1. http://insurmarket.myfreeip.me/what_is_policy_in_insurance.xml (reply)

      The factors they are usually varied. You can also have a teenage driver is found not to rush into making a claim, it is the amount you would wantsaves money in your blog. The internet, takes the load and it is and how many people will be based on various coverages. Comprehensive and collision coverage in their pricing. bepersonally, you will be bidding), and not pay off. Young women, in general, prefer to just custom order your car on the shopping partners and husbands also to ease congestion. 2psomething unexpected should happen you could do when you mention the other automobile that we will get excellent coverage, you may have to pay the claim should arise. You could totoss the excess would have been receiving. In these instances, you may qualify for an auto policy but do not need to pay before the change is hard to find thathigh you can’t find PA auto insurance rates, it does not have an accident the liability (the insurance customer) for $100K. The customer now owes the bank wants Full Coverage Insurance?to get across the ideal combination of benefits and some even do it yourself. Do not simply missing out on the employers of younger motorists. In these cases, the acquirement thesequotes quickly is usually 2 to 15 guests.

    2. kfz haftpflichtversicherung pramie (reply)

      Personnellement, je ne rentrerais pas dans la polémique même si comme le dit Urus d’autres questions « urgentes » sont encore en suspends vis-à-vis de ce conflit mais effectivement le recours à l’énergie solaire est assez intéressant. Si nous ne pouvons pas éviter les guerres et autres conflits mondiaux, réjouissons nous au moins que malgré tout ça, les énergies plus écolo sont utilisées

    3. http://www./ (reply)

      Time fer some perdictions: Niners vs da Rams. Who you gonna call? Phil: 28-20 Niners. This is our last 2am game of the year and the only reason I’m watching (listening) is because of Colin Kaepernick. I think the D rises to the ocassion and shuts dow Amendola.

    4. http://www./ (reply)

      Öncelikle Türk yazın dünyasındaki önemli bir eksikliÄŸi giderdiÄŸiniz için sizlere teÅŸekkür ediyor. Türk milletini, Türk dünyasını önceleyen ve bu hususta hasbelkader kalem oynatıp, fikir yürütmeye çalışan birisi olarak, her türlü faaliyetinize imkanlarım ölçüsünde koÅŸulsuz destek vereceÄŸimi bilmenizi istiyorum.. DeÄŸerli aÄŸabeylerim, kardeÅŸlerim, arkadaÅŸlarım… Listeyi uzatmadan özetlemek gerekirse saygıdeÄŸer gönüldaÅŸlarım; GiriÅŸtiÄŸiniz kutsal yolunuz kutlu ve daim olsun.. Allah (c.c) yar ve yardımcınız olsun! Selam, saygı dua ile… Harun Kılıç/Ankara

  6. Mav21 (reply)

    Hi Rob, I’ve used this method on a few projects recently. Works great! I have now run into a minor problem in a dynamic environment though. When I close the alert box on product 1’s page, it still shows when you open product 2’s page (same page, different content from database and different URL rewritten address). Any idea how to resolve this? Does it have to do with the difference in URL? Thanks!

    1. Rob Glazebrook (Author) (reply)

      Hi David,

      It looks like on your second site you’re merely hiding the box onclick… you’re not setting a cookie or anything. The cookie is the part that makes the box stay closed.

  7. Pingback: links for 2010-09-17 – Chris Dalby Untangles Networks

  8. aytacgul (reply)

    Excellent. But i need to use 3 different message box! And your script for 1 box only. How can i use this a script for 3 different message box????

  9. JPM (reply)

    Hi Rob, great tutorial… Just a few questions.

    I’m using Thesis theme, and using the close function slightly different… Infact I’m using it for an image header, but want to give the site visitor the option to close it. The image header is contained within the feature box.

    In Thesis, there is there is a feature called ‘feature_box’ which I’m using to do this. But it doesnt have a ‘class’ element… Only ‘ID’ element. You said it would be faster and easier to reference that…?

    How does the last function change in that case, I want to check for the id=”feature_box” and then only show the feature box.

  10. Krishan (reply)

    Hi Rob,
    Just discovered Your tutorial -Thanks for this – I’m using Your box for displaying newyear-greetings …- I have one question: (How) is it possible to set the time to expire in minutes and not in complete days?

    greetings and best wishes for new year Krishan

  11. AKBAR ALI (reply)

    Great tutorial. I am using it. But I want to keep it hidden for 4 minutes only. Is it possible. You said it can be used for various message with different id. How,Could you please give me slight hint.

  12. uberstrike hack tool mac (reply)

    I know this iif off toic but I’m looking into starting my
    own weblog and was curious what all is needed
    to get set up? I’m assuming haing a bloog like yours would cost a pretty penny?
    I’m not very internet smart so I’m not 100% sure.
    Any tips or advice would be greatly appreciated. Many thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>