Groovy bitsbringing new skills to your web development team

Flicker Fix

Summary

This page tells you how to use ASP.NET to eliminate the flicker sometimes seen in menus implemented with cascading style sheets (CSS).

Background

For as long as authors have been experimenting with pure CSS menus there have been reports of flicker problems.

The emerging view is that the problem is ultimately caused by the client browser failing to cache images used in hover styles (CSS).

One way to eliminate this flicker is to specially configure your web server (e.g., IIS). Then, when these sorts of rollover images are requested, your web server will add specific caching requirements to the HTTP headers. These tell the browser to cache the images regardless of the default caching policy it normally uses.

Unfortunately, this sort of solution is only practical when you have access to your web server's configuration. Most web hosting services do not give you access to the IIS management console. Even when IIS can be directly accessed, configuring caching policies is scary and unfamiliar to many authors.

Happily, there is a much simpler solution if you are developing a web site with ASP.NET. It's is easy to implement and doesn't involve configuring your web server.

Solution

To implement this solution you will:

After adding the HTTP handler PersistantImage.ashx to the root of your web app, locate styles that refer to background images. Imagine your web site has a subfolder just below the root where you put all your style sheets. It might have a class that defines the background image used in a menu:

CSS
1
2
3
4
5
        .someClassName
        {
            background:#AABBCC url(someFlickeringImage.gif) repeat-x;
        }

If you find that the menu flickers, you could modify this style to be:

CSS
1
2
3
4
5
        .someClassName
        {
            background:#AABBCC url(../PersistantImage.ashx?key=SomeFlickeringImage) repeat-x;
        }

Then you would add an entry defining the query string key, SomeFlickeringImage, in the appSettings section of the web.config in the root of your web app:

CSS
1
2
3
4
5
6
7
8
9
10
        <?xml version="1.0"?>
        <configuration>
          <appSettings>
            <add key="SomeFlickeringImage" value="~/myStyles/someFlickeringImage.gif"/>
          </appSettings>
          <system.web>
          </system.web>
        </configuration>
        

This forces the browser to request the background image via the HTTP handler, PersistantImage.ashx, rather than requesting that image file directly. You provide PersistantImage.ashx with a nickname for the image via the key in the query string. PersistantImage.ashx looks up that nickname in the appSettings to find the true path to the image to send down to the browser with special caching instructions. Because the browser now caches the image it doesn't re-request it from the server again and again, which is what causes the flicker effect.

Using nicknames for images enhances your web site's security. Your web.config contains a white list of images that you explicitly allow to be exposed. No one can invoke PersistantImage.ashx directly to gain access to other files on your web site.

As an added security measure, the HTTP hander PersistantImage.ashx will only respond to requests for files with a web image extension: jpg, jpeg, gif or png.

If you are using the CSS Friendly ASP.NET Control Adapters you will find it helpful to modify the style sheet that defines the background images used for menus.

One of the styles to change is:

CSS
1
2
3
4
5
        .PrettyMenu ul.AspNet-Menu li
        {
            background:#4682B4 url(bg_nav.gif) repeat-x;
        }

It should become:

CSS
1
2
3
4
5
        .PrettyMenu ul.AspNet-Menu li
        {
            background:#4682B4 url(../../PersistantImage.ashx?key=BasicBgNav) repeat-x;
        }

Then, in the web.config you would modify the <appSettings> to be:

CSS
1
2
3
4
5
6
7
8
9
10
        <?xml version="1.0"?>
        <configuration>
          <appSettings>
            <add key="BasicBgNav" value="~/App_Themes/Basic/bg_nav.gif"/>
          </appSettings>
          <system.web>
          </system.web>
        </configuration>
        

You may find that you need to use PersistantImage.ashx in several different styles in order to fully eliminate the menu flicker. In practise it is probably easiest to adopt a simple policy of using PersistantImage.ashx for all of the menu-related styles that refer to background images.

Legal

Disclaimer

© 1999-2009 Groovy bits