IE Bug dealing with CSS custom cusors

Welcome to another addition of Beating IE into submission!

Before I get started though, I have to make a confession. This article won't be so much about beating IE into submission as it will about IE having beaten me into submission!

Unfortunately, this is one case I wasn't able to come up with any great solutions. All I'll be able to offer at the end of this article, are three (relatively unsatisfying) work-arounds. Which one is least-evil… I'll leave that up to you.

So what is this mysterious bug I'm referring to? Read on to find out.

First a little background on CSS custom cursors.

Suppose you've created a nifty custom cursor that you want to use as the default cursor in your web site. The simplest way to this would be to create a CSS style rule on the <body> element that specified this custom cursor:

body
{
   cursor: url("http://my.site.com/custom.cur"), auto;
}

This tells the browser to attempt to load http://my.site.com/custom.cur and use it as the cursor whenever the mouse is over the <body> element. The ,auto is a fall-back, so in case the custom cursor can't load (for whatever reason) the next cursor in the list will be used.

So far so good. But suppose we don't want to specify a complete URI as I've done in the preceding example. No problem; simply change the path to be a relative one:

body
{
   cursor: url("./custom.cur"), auto;
}

In this example, we're telling the browser to load the file, custom.cur from the current folder (the one in which the CSS file resides).

We can go further with this relative "pathing":

body
{
   cursor: url("../custom.cur"), auto;
}

Here we're telling the browser to go back one level, and load the file, custom.cur from there. So if, for example, you keep all of your stylesheet files neatly organized in a directory called /css/, this would tell the browser to go back one level (to the root of the web site) and load the custom cursor from there.

Well… almost. That is what should happen, and is every worthwhile browser on earth, that is in fact what does happen. Not so in IE6 or 7.

If you were to take any of the above style rules, and paste them directly into your HTML source file inside of a <style>...</style> block, all would work as expected.

However, the moment you take your style rules out of your HTML source file, and place them in an external file, all bets are off!

It seems that IE does not understand how to evaluate the relative path of a cursor: rule, which is mind-boggling considering that IE (somehow) manages to get it right when it comes to CSS background images!

So what does IE do exactly? It evaluates the relative path of the cursor: rule using the HTML source document's URI as the base URI.

This is so completely and totally, mind-numbingly, punch-yourself-in-the-face stupid, that it makes me want to punch myself in the face!

For one thing, it's a complete lack of consistency that IE handles relative paths differently for images than it does for cursors. For another thing the W3C specifications say quite clearly:

In order to create modular style sheets that are not dependent on the absolute location of a resource, authors may use relative URIs. Relative URIs (as defined in [RFC3986]) are resolved to full URIs using a base URI. RFC 3986, section 5, defines the normative algorithm for this process. For CSS style sheets, the base URI is that of the style sheet, not that of the source document. (emphasis mine).

So what does this mean in a real-world scenario? It means that the same style rule won't work in both IE and W3C browsers if your CSS lives in an external file. For example:

– styles.css
body
{
   cursor: url("../custom.cur"), auto;
}

– index.html
<html>
   <head>
      <link rel = "stylesheet" type = "text/css" href="./css/theme1/styles.css" />
   </head>

   <body>
   </body>
</html>

In the preceding example, the proper evaluation of the cursor: rule is as follows:

../custom.cur means "load custom.cur, which is located one level up from the CSS source file (styles.css)."

The path to styles.css is ./css/theme1/style.css, which is itself, a relative path whose base URI is determined from the file linking it (in this case, index.html).

If we assume index.html lives at the root of the web site, then we can conclude that the absolute path to style.css is:

http://{some_website_addr}/css/theme1/style.css

Since the cursor: indicates that the custom cursor is located one level up from the CSS source file, this would mean that the browser expects to find custom.cur at:

http://{some_website_addr}/css/custom.cur

Remember, this is what a good, W3C compliant browser would do. This is most definitely not what IE does.

IE evaluates the relative path incorrectly. It uses the HTML source file (index.html) to obtain the base URI for normalizing the URL specified in the CSS cursor: rule. This means that IE will try to look one level up from the web site root for custom.cur.

Acute readers might have realized that one level up from the web site root is precisely nothing! It has no meaning, and it will of course, fail. But the relative URI need not resolve to something meaningless as it does in this example; any URI that IE gets a hold of is almost certainly going to resolve to the wrong URI.

"But wait," I can hear at least 50% of you shouting, "I've gotten relative cursor paths to work in IE."

To this I reply emphatically "No you haven't!"

Any time it has worked in IE is sheer coincidence. IE always interprets relative cursor paths incorrectly. Sometimes though, the incorrect interpretation just happens to be the same as the correct interpretation, which brings me to my first work-around.

Work Around Option 1:
Rather than putting your cursor: rules in an external file, put them all in a <style>...</style> directly in your HTML source file.

This works because when IE always resolves the base URI from the HTML source file no matter what. W3C browser will resolve it from the wherever the CSS style rules are located (which in this case happens to be the HTML source file). Thus, both browser start from the same base URI, and life is peachy.

Putting your style rules directly in your HTML file kinda sucks though, because it totally destroys style re-usability.

Work Around Option 2:
Instead of using relative paths, use absolute paths. This will work in all browsers, so that is the main advantage of this approach. However, it kills flexibility because if your web site structure changes, chances are good you'll have to manually update all your styles rules, which is tedious and error-prone. Boo!

Work Around Option 3:
Use IE conditional comments to load a specific IE stylesheet. Make sure your IE-specific stylesheet comes after all other stylesheet links, and you'll be able to override the correct cursor: rules with some whacky cursor: rules that will make silly 'ol IE happy as a clam.

So there you have it. Three crappy work-arounds for a crappy bug from a crappy browser.

But there is hope! Because when I'm President, I'm going to make IE illegal :-)

Comments Welcome.

10 Responses

  1. Bryan Says:

    First, my thanks for explaining the problem I was having.

    With that said, I will go with option 2. It actually works well for my project because the files will be heavily reused and scattered through the file system. So, I won’t have to worry about deciphering forty million dot dot slash’s. lol

    So, when do you hit the campaign trail? IE must die!!! lol

  2. Stephen Stchur Says:

    "When do I hit the campaign trail?"

    HA! If only I had the time and energy…

    To be fair, IE7 has come a long long way. Hopefully we'll see the use of older versions of IE continue to decrease at a rapid rate.

    Until then, we do out best to work around the issues!

  3. Piotr Skowronek Says:

    The 4th solution:
    add alternative, IE-specific, path to the cursor tag, for example:

    cursor: url("../fancy-cursor.cur"), url("imgs/fancy-cursor.cur"), auto;

    (Of course IE will probe for the first one, and will find nothing, in
    consequence this can cause some latency, but - we can consider it as some
    kind of punishment for using IE :d)

    This way, you can add other alternatives, for example cursor
    in png format, which might be better for other browsers, that do not
    understand CUR/ico format.

  4. Dutchki Says:

    How about using an absolute path reference as the first and catch-all solution?

    I always use the format url('/path/to/file'), and have yet to see any issue, regardless of locations, folders, subfolders, sub-subfolders, sub-sub-subfolders, sub-sub-sub-su-… you know what I mean. Using the / quantifier always assumes the root of your domain. And if you're one of those silly GeoCities or Yahoo! accounts, just use url('/youraccount/path/to/file')…

  5. sstchur Says:

    Dutchki,

    Yes, this will work, and it might be just the thing for some people.

    However, it may not be a convenient solution if relative pathing is desired (as it sometimes is).

  6. Alaink Says:

    Hi, I'm having the same problem with a dynamic java web application.
    Is there a way to use a html bloc in the html head section and "absolute" paths in css files based on the html url?

  7. Alaink Says:

    Sorry, html blocks have been filtered from my previous posting:

    Hi, I'm having the same problem with a dynamic java web application.
    Is there a way to use a <base> html bloc in the html head section and "absolute" paths in css files based on the html <base> url?

  8. Dutchski Says:

    Alaink:

    For applets and scripts, a fixed location or root path combined with <base> always works best (as in: most reliable, *if* you keep all your applets/scripts in a predefined location).

    As far as anything else goes - it appears there's a web-wide discussion/confusion on what the best method is. Saila (http://saila.com/webdesign/tips/linking/) makes a good argument:

    "If the site has a basic hierarchical structure, relative links are the best choice. Complex sites, or those with dynamically generated pages (like this one), are usually best served by absolute links."

  9. Madster Says:

    I know this post is old but it took me a while to figure out.

    IE6, Opera and Webkit do not support custom cursors over image map areas at all.
    Firefox 3 does.

    Don't know about other IEs or browsers.

  10. relative oder absolute Pfadangabe - XHTMLforum Says:

    [...] innerhalb CSS Dateien. Im Gegensatz zu Firefox konnte IE die Pfade nicht finden. Hier ist ein Blog Eintrag zu diesem [...]

Got something to say?

Please note: Constructive criticism is welcome. Rude or vulgar comments however, are not and will be removed during moderation.


purchase accutane online buy accutane cialis prescription order cialis without prescription buy cheap soma online generic synthroid accutane pills cheapest generic viagra lowest price acomplia propecia without a prescription cheap cialis from usa tablet viagra certified viagra buy cialis without prescription levitra discount cheap viagra in usa lowest price clomid order cheap viagra acomplia sale cialis rx order lasix viagra bangkok cheapest cialis prices online viagra cialis vendors buy soma online clomid sale buy cheap lasix online viagra free sample cialis in us viagra canada buy cialis from us soma no prescription cialis pill buy soma buy viagra in us soma for sale where to order viagra viagra buy drug viagra buy cialis in uk synthroid cheap cheap generic cialis buy cheap synthroid online discount propecia acomplia pharmacy order lasix online buy cialis in us soma without a prescription cheap propecia tablets cheap viagra tablets find cheap cialis cialis sales clomid online stores clomid prices compare viagra prices online cheap cialis no rx lasix without prescription cialis pills cialis purchase online pharmacy viagra buy cheap accutane find viagra on internet cialis order buy viagra cheap cheapest levitra cost of viagra cheap lasix tablets order cialis on internet order viagra in canada zithromax no prescription lowest price zithromax cheapest viagra prices