How to build Growl-style notifications with jQuery

Mac OSX is able to display message notifications — still referred to as Growl messages, despite the fact that the big cat moniker is no longer applied to versions.

Many applications send Growl messages to the OS to let the user know that an action has just occurred.

Wouldn’t it be nice to use messages like this on our websites? I think so. In this tutorial we’ll construct a notification like this with HTML, CSS3 and a little jQuery.

Growl message functionality

When more than one message is displayed, the messages are stacked on top of one another. They also fade out by default unless the user hovers the mouse over the message. There’s also a drop shadow around the message.

This is what we’ll build.

Creating Growl-style messages with HTML and CSS

We’re going to build this functionality as a jQuery plugin. As with any jQuery plugin our goal is to keep not only JavaScript, but also HTML compact. We’ll use <ul> and <li> tags to construct the message box:

<!-- The main container location, this is where all messages will appear //-->
 <div id = "jqGrowlContainer"></div>
 <!-- Blueprint CSS, used to clone messages, always hidden //-->
 <ul id = "jq-growl-clone">
 <li class = "title"></li>
 <li class = "msg"></li>
 <li class = "icon"></li>
 <li class = "close"></li>

The div#jq-growl-clone element is the style of each message box that will appear. Remember that more than one message can be displayed at once on the screen.

We don’t have to type the multitude of messages that may or may not appear, we’ll create them with JavaScript.

In particular, we’ll write HTML cloning code using the append method to add the message to the queue and the html method to grab a copy of the HTML from the clone element.

There are several elements that make up the message box: the icon, message title, message itself and the close button. There are also various visual styles applied such as the gradient, rounded corners and the outset CSS shadow.

The CSS is a little lengthy, mostly because of the visual effect code that works in multiple browsers. If we only had one browser to develop for, this code would be shorter.

/* The clone container is always hidden */
 #jq-growl-clone { display: none; }
/* The main style of our HTML Growl message, anything you want */
 #jqGrowlContainer ul { display: block; position: relative; border: 1px solid gray;
 padding-top: 4px; padding-bottom: 4px; }
 #jqGrowlContainer ul li { display: block; font-size: 12px; font-family: Arial, sans-serif; }
 #jqGrowlContainer ul li.title { font-weight: bold; }
 #jqGrowlContainer ul li.icon { position: absolute; top: 4px; left: 4px; width: 32px; height;
 32px; background: url('jq-g-icon.png') no-repeat; }
 #jqGrowlContainer ul li.msg { margin-right: 24px; color: gray; }
 #jqGrowlContainer ul li.close { position: absolute; top: 4px; right: 4px; width: 14px;
 height: 14px; background: url('jq-g-close.png') no-repeat; cursor: pointer; }
/* This is the position of the main message queue container
 It can be adjusted using the first parameter of $.jqGrowl.init method
 #jqGrowlContainer {
 position: fixed;
 top: 0;
 right: 0;
 width: 320px;
 border: 0;
/* Rounded corners */
 #jqGrowlContainer ul {
 -webkit-border-radius: 7px;
 border-radius: 7px;
/* Let's add a shadow to the message for web-kit and standard browsers */
 #jqGrowlContainer ul {
 -webkit-box-shadow: 0px 0px 7px 1px rgba(50, 50, 50, 0.3);
 box-shadow: 0px 0px 7px 1px rgba(50, 50, 50, 0.3);
/* This code adds a gradient to the message. It was built using the CSS gradient generator found on Google search. */
 #jqGrowlContainer ul {
 background: -moz-linear-gradient(top,  rgba(0,0,0,0) 0%, rgba(0,0,0,0.22) 100%); /* FF3.6+ */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0.22))); /* Chrome,Safari4+ */
 background: -webkit-linear-gradient(top,  rgba(0,0,0,0) 0%,rgba(0,0,0,0.22) 100%); /* Chrome10+,Safari5.1+ */
 background: -o-linear-gradient(top,  rgba(0,0,0,0) 0%,rgba(0,0,0,0.22) 100%); /* Opera 11.10+ */
 background: -ms-linear-gradient(top,  rgba(0,0,0,0) 0%,rgba(0,0,0,0.22) 100%); /* IE10+ */
 background: linear-gradient(to bottom,  rgba(0,0,0,0) 0%,rgba(0,0,0,0.22) 100%); /* W3C */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#38000000',GradientType=0 ); /* IE6-8 */

Notice how everything stems from the #jqGrowlContainer element, and #jq-growl-clone is hidden by default. We will clone the UL residing within #jq-crowl-clone into the main container (#jqGrowlContainer) element, every time a new message is added to the queue. This is the very reason why #jqGrowlContainer (and not the hidden clone element) is the root. The style is only applied to what is inside #jqGrowlContainer.

The message queue is represented by a UL/LI construct. In other words the UL is the master container for one individual message. And the LI inside it represent various elements of the message.

Looking at the clone element, you’ll notice that each message is wrapped within the main UL tag. That is what will be cloned into the main container element every time a message is added to it. Moreover, it will not be simply copied into the main container, but it will be appended to the content that already exists in the main container.

Building the Growl plugin

Finally, we can glue this all together by creating a jQuery plugin. You’ll notice the use of the jQuery library to perform actions such as appending messages to the queue (without removing existing ones). And also the onClick event created using the jQuery’s .on method for attaching events to HTML elements.

msg_ctr = 0;
 $.jqGrowl = {
 timeout: 3000, /* 3 seconds default timeout */
 init: function(corner, timeout) {
  msg: function(message, title) {
 // Store objects for reuse
 var container = $("#jqGrowlContainer");
 var clone = $("#jq-growl-clone");
 var tag = "#jqmg" + msg_ctr;
 // Fade out after a period of time (3 sec. default)
 setTimeout(function() { $(tag).fadeOut(2000); }, $.jqGrowl.timeout);
 $("ul", clone).attr("id", "jqmg" + msg_ctr);
 $("li.title", clone).text(title);
 $("li.msg", clone).text(message);
 // Append this message to the queue
// Attach close button event
 $(tag + " li.close").on("click", function() { $(tag).fadeOut(300); });

Each time a new Growl message is added to the queue, it is added to the main message list. The global msg_ctr value is used to track the number of the message so that it can be faded out using jQuery’s fadeOut method.

Perhaps the most important function of the plugin is copying the clone message into the main message queue using jQuery’s methods append and html.

The code to initialize the plugin is shown below:

<script type = "text/javascript">
 $(document).ready(function() {
 $.jqGrowl.init( { position: 'absolute', bottom: '8px', right: '8px' }, 5000);

That’s it! You can now begin using the plugin on your own website. The purpose of the code you’re seeing above is to initialize the plugin and give the main #jqGrowlContainer a position relative to the screen.

To initialize the Growl queue so that it appears in the lower left corner of the screen, simply change the CSS code passed to the init function:

 position: 'absolute',
 bottom: '8px',
 left: '8px'
 }, 5000);

These are just regular CSS styles, you could use the combination such as { top: 8px, right: 8px } to move the queue to the upper right corner of the screen, etc. You decide where the queue will appear. You can even change the values here to make the messages appear in the middle of the screen or inside particular container on your website.

The last value 5000 (here, in milliseconds), indicates that the message will fade out in 5 seconds from the time it appears on the screen. You can provide your own timeout value. You can also close the message at any time by clicking on the close button.

Greg Sidelnikov has been writing programming tutorials since 2004, he tweets free tutorials/demos at @gregsidelnkiov. More articles by Greg Sidelnikov
  • DH

    Is there a demo link of this? Much interested or combined html file?

  • temporaryuser381

    Demo or it didn’t happen!!!

Home CSS Deals HTML HTML5 Java JavaScript jQuery Miscellaneous Mobile MySQL News PHP Resources Security Snippet Tools Tutorial Web Development Web Services WordPress