Back in September 2007, I posted an article which described a way to “disable” an UpdatePanel (or more specifically an entire page) by using a modal UpdateProgress control. This solution would allow developers to stop users from clicking on other items on the page while the UpdatePanel is processing. The premise behind this was taking a DIV and stretching it over the top of the page using CSS, and having a message (e.g. “Please Wait”) on top of that. This is achieved by using some simple CSS. If you want to read the original article, you can view it here.

Since that time, this continues to be one of the most popular posts and many people have wanted to use this solution with IE 6. Well, the original version showed the message, but not the “blanket” modal DIV in IE 6. There were also issues with scrollbars where the “blanket” would stay at the top and users could still see the bottom of the page if they scrolled. I’m happy to say that there is a solution to these issues… The following techniques were tested in IE 7 (7.0.6001.18000), Firefox 2.0.0.12, and IE 6 (6.0.2900.2180) in Standards Mode.

First, the code is the same, but instead of going back to the old post, here it is again:

<asp:updateprogress associatedupdatepanelid="UPDATEPANELID"
    id="updateProgress" runat="server">
    <progresstemplate>
        <div id="progressBackgroundFilter"></div>
        <div id="processMessage"> Loading...<br /><br />
             <img alt="Loading" src="images/ajax-loader.gif" />
        </div>
    </progresstemplate>
</asp:updateprogress>

Pretty simple code… basically the only “custom code” are the two DIVs. The first, progressBackgroundFilter is used to blank out the page. The second, progressMessage, is the message to display. In this case, it’s just text and an animated gif.

Solution for IE 7 and Firefox

Now for the styles, this is where we will fix the problems in the old solution. First, let’s start with IE 7 and Firefox. The old solution worked well, however it had a problem with scrollbars. To fix this in modern browsers, we will use the CSS property position: fixed.

#progressBackgroundFilter {
    position:fixed;
    top:0px;
    bottom:0px;
    left:0px;
    right:0px;
    overflow:hidden;
    padding:;
    margin:;
    background-color:#000;
    filter:alpha(opacity=50);
    opacity:0.5;
    z-index:1000;
}
#processMessage {
    position:fixed;
    top:30%;
    left:43%;
    padding:10px;
    width:14%;
    z-index:1001;
    background-color:#fff;
    border:solid 1px #000;
}

The only difference in this code is the position (which I have made bold and underlined in the snippets above). We are utilizing position: fixed, which means to pin the elements to the viewport regardless of the scroll position. Previously, we used position: absolute; which caused our “blanket” to position itself relative to the original viewport, but not the entire page, so the problem came about when there are scrollbars.

Fun (not) with IE 6

Now, for IE 6 (Note, it may work in other versions of IE, but I haven’t tested it). The problem with the initial solution was that IE 6 ignored the right and bottom CSS styles. All we could see was the processMessage DIV, but not the background filter. A first attempt at fixing this was to add a height and width to the progressBackgroundFilter for anything below IE 7. A width of 100% stretched it horizontally, but a height of 100% did nothing. Obviously a fixed height, e.g. 200px worked, but not much use when we don’t know the height. After a bit of research, I came across an article titled “Conflicting Absolute Positions” by Rob Swan, which greatly helped in coming up with a solution. IE 5 and 6 offer an alternative to just percents and fixed sizes, it allows us to dynamically set styles by using an expression. An expression is just a JavaScript snippet for a given value. Have a look at “Conflicting Absolute Positions” for more information on IE’s CSS expressions. Without further ado, here’s the complete CSS for IE 6:

body { height: 100%; }

#progressBackgroundFilter
{
    position:absolute;
    height: expression(document.body.clientHeight + "px");
    width: expression(document.body.clientWidth + "px");
}
#processMessage {
    position:absolute;
    top: expression((document.body.clientHeight * .30) + "px")
}

First, as mentioned, IE 6 doesn’t understand position: fixed; and reverts back to position: static, so the first step is to set position to absolute only for IE 6 and below in both the #processBackgroundFilter and #processMessage. The rest of the styles utilize expressions, with the exception of body style above, which I will discuss in a bit. The premise behind the expressions is to calculate the full page dimensions and position the background filter. For the message, I wanted to appear in the viewport 30% from the top of the screen like the IE 7 / Firefox counterpart, so that is why there is a calculation for the top. The thing that doesn’t happen with the message that does occur in IE7 and Firefox is that the message “follows” the user if they scroll. You could do capture the scroll event and move the message, but I feel this is overkill, plus it complicates the simplicity of the “Modal UpdateProgress” solution.

One thing to note here is that the expressions are using JavaScript, if a user has JavaScript disabled, the CSS expressions do not work. However, if they don’t have JavaScript enabled, the expressions are the least of your problems. Their overall AJAX experience will be non-existent. Just note this if you use expressions in other types of applications.

Anyway, in trying to getting this to work I encountered some issues with the JavaScript calculations and getting everything to work in sync. One thing to note here is that IE 6 is overly sensitive to DOCTYPE declarations making it difficult when dealing with box models (e.g. quirks vs. standards). On my pages, I use the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

For determining if IE 6 will be rendered in quirks mode vs. standards mode, I typically refer to the Wikipedia’s Quirks Mode page and the document type comparison that they have. I like to work in standards mode since that is what modern browsers use, but the DOCTYPE for XHTML 1.1 isn’t in the list, but XHTML 1.0 is, and further down the page it does list XHTML 1.1 as standards rendering. So, I went over to QuirksMode.com and referenced the article titled “document.body and doctype switching,” which was very helpful.

Originally, I simply had the expressions for just the two elements and this was the result when the browser was maximized:

Figure 1 IE6 Without Height

Figure 1 - IE 6 without body { height: 100%; }

Notice the issue with the bottom of the page in Figure 1? The progressBackgroundFilter doesn’t cover everything. I tried all sorts of stuff, then using the IE Developer Toolbar, I saw what was happening. since the page I was on was short, the body element only expanded just to the bottom of the content. I have no idea though why it’s still just a tad shorter than the body as shown in Figure 1 (see the bit of darker blue that is peeking out?). I believe it has to do with body padding and or margins, but my investigation on the topic ended there; I just chalked it up to IE 6 baffling me sometimes. Anyway, I thought to add the height: 100%; style to the BODY element. This turned out much better as shown in Figure 2 below.

Figure 2 IE6 With Height

Figure 2 - IE 6 with body { height: 100%; }

Much better, but your solution to the IE 6 woes may differ to mine. My basic styles on this site are as follows:

body { margin:0; padding:0;}
#container { margin:10px auto; }

You can see the body has no margin or padding (this would push out the body in IE 6 because it would be 100% + the margin and padding causing the page to scroll when it didn’t have to). I achieve the margin on the top and bottom by assigning these to my outer container which is just a DIV where all the content lies. Your design may not permit you to do the height: 100% trick, but in my case it was the solution.

IE 6 - Other attempts at a solution (more fun)

When playing around with IE 6, I attempted all sorts of things before using, the one solution that worked about 90% is as follows:

#progressBackgroundFilter
{
    position:absolute;
    height: expression(document.documentElement.scrollTop + document.documentElement.clientHeight + "px");
    width: expression(document.body.clientWidth + "px");
}
#processMessage {
    position:absolute;
    top: expression(document.documentElement.scrollTop + (document.documentElement.clientHeight * .30) + "px")
}

The thinking behind this was to take the window height (which document.documentElement.clientHeight gives us) and then add the scroll top position, which will give us the upper portion if the user scrolls up. The problem shows itself when the user scrolls down; that area is not covered. The good thing about this is that I didn’t need to mess with the body height, but the solution isn’t optimal in the long haul. Note this solution does work in the maximized state unlike other attempts (e.g. Figure 1 from earlier).

The purpose for me adding this “solution” is my hope that you, the reader, can come up with a solution that doesn’t involve body { height: 100%; }. Hopefully these attempts may help you come up with something a bit better. As stated earlier, the height thing can throw off some overall designs that you may have, for example if you have a margin or padding on your body element, your page will be that much longer.

Putting it all together

To get these styles to work with IE 7, Firefox, and IE 6, we need some technique to hide the IE 6 code from the other browsers. This is easily achieved without hacks and such by using a conditional comment. Conditional comments allow us to specify CSS code for a certain browser or range of browsers, hiding it from others.

The syntax for a condition comment follows a standard HTML comment (e.g.<!-- This is a comment -->) so that most browsers will simply ignore it. Internet Explorer however recognizes the <!--[if IE]> and processes it as part of the page. You can use specifics such as a straight browser version or a range using “lt” for “Less Than”, “gt” for “Greater Than”, and you can append an “e” (e.g. “lte” and “gte”) for “Or Equal To”.

In this case, we want to apply the IE 6 specific CSS to anything less than IE 7 (so the syntax is <!--[if lt IE 7]>). Here is snippet of what my HEAD section looks like, complete with conditional comment:

<head>
    <title>Visoft Inc.</title>
    <link href="styles.css" rel="stylesheet" type="text/css" />
    <!--[if lt IE 7]> <style type="text/css">@import "ie6.css";</style><![endif]-->
</head>

The IE 6 specific logic resides in the file ie6.css while everything else is in styles.css. Since the IE 6 specific stuff comes after the generic stuff, the styles will be overridden only for IE 6.

The end results

You’ve already seen a snapshot of IE 6, so here is what IE 7 and Firefox look like:

Figure 3 - IE7 with Modal UpdateProgress

Figure 3 - IE 7 with the Modal UpdateProgress

Figure 4 - Firefox with the Modal UpdateProgress

Figure 4 - Firefox with the Modal UpdateProgress

With this revised solution you should be able to use this approach in more designs where you need to disable the rest of the controls from the user. I feel that this is a nicer option that hiding content on the page or whatnot to achieve the same thing. The user’s experience is very important to the success of an application in the user’s eyes, so the nicer the UI, the better your application is perceived.