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.

24 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 […]

  11. tee Says:

    Das Problem ist, dass der Startpunkt des relativen Pfades beim IE nicht die CSS-Datei ist, sondern die Position der HTML-Seite welche das CSS einbindet!

    hass hass hass!

  12. SL Says:

    Baffling, really. For anyone using a CDN for static file hosting, this is a headache. Having relative paths to the CSS file is an absolute must since the document and css file have use different domains altogether.

    I am absolutely shocked to find this post from 2006 and realize this bug can still be found in IE8. I mean – WTF?????

  13. Joey Bendlage Says:

    Very helpful!!

  14. Strategy war game Says:

    Same bug still exists in IE9 πŸ˜›

    This is a PITA as all my CSS + images are located on different servers.

  15. Custom Cursor with click animation + crossbrowser support | Nuclear's Blog Says:

    […] AGAIN, here comes shitload of problems again: 1) locating .cur files for CSS cursor is so buggy and retarded, this bug exists I think in all IE versions (atleast IE6-9 it does). I didn't want to waste […]

  16. keith Says:

    wow. 5 years and 2 months later, I came across this post and it explains the issue ever so well. We don't support IE7 much anymore, but when IE7 users would hit our site, it would try and grab a url that didn't exist and was causing some load on the server.

  17. sstchur Says:

    Glad it helped!

  18. LauraF Says:

    Thanks for this…I scratched my head for an hour over a DNN site….it worked in firefox and chrome, but not in IE…I put an absolute path in the css and it worked like a charm.

    Also, you have a great writing style… I absolutely adore this paragraph…
    "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!"
    Thank you for the laughs!
    Laura

  19. Paulo Says:

    Thanks!!!!
    It solves cross browser:
    cursor: url(./Content/imagens/myCursor.cur), url(../imagens/myCursor.cur), pointer;

  20. Augustine Says:

    Damn I was going to ask the same question. I've spent ages biidlung my site and wanted to make an enter or welcome page with just a blank background with just a flash animation of a logo that would link to the homepage but can't get rid of the header or change the bg color without the rest of the site getting affected. Quite a big oversight if you ask me, I'm surprised Weebly haven't got an option for it!

  21. Radu Says:

    the next step would be to also cover having custom cursor hotspot which also requires a workaround for compatibility. I am sure the result of combining the workarounds together will be some disgusting css, all thanks to IE

  22. Rob Donovan Says:

    Damn, so its 2015, we are now on IE11 and this is STILL a bug! πŸ™

    What do MS coders and tests do!

    Thanks for the explanation though, thought I was going mad.

  23. Jeremy Says:

    Just ran across this. Couldn't for the life of me figure out why my stylesheet wouldn't accept my cursor. Thank you so much for this page!!

  24. Alessandro Says:

    July 2016! bugs still present, in ie 11 and microsoft edge!
    Infinite thanks for your decades end useful guide! πŸ˜‰
    But I think the fault lies with us webmaster! Why we insist on solving user problems which still persist to use ie ??? hahahaha. We will learn never to abandon them? πŸ™‚

Got something to say?

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