Posts Tagged ‘cursor’

Cross-browser custom CSS cursors

January 8, 2008 102 comments

I saw sometime ago the funny drawing below.
Time breakdown of modern web design

You can see that big portion is for making the design work in Internet Explorer.
First you laugh, but if you developed rich web sites/user interfaces you actually realize that this is only underevaluated. I would also extend it and say “make the design cross-browser”.

The tip that I’ll present you next it’s actually a small workaround and it will help you reduce that big pie slice.

Let’s say that you want to change the cursor for a page, for links or for some other specific elements. How? Using CSS. Then we should first go at W3C and read how to do it.
So the cursor property is the answer.
As good web developers we will separate the CSS from HTML and create the following structure

  +-- cursor.html
  |-- cursor
      +-- cursor.css
      |-- cursor.cur    
  • cursor.html
        <link rel="stylesheet" type="text/css" href="cursor/cursor.css">
        Hello world!
        Look at me, I have a new cool cursor! 
  • cursor.css
    BODY {
        cursor: url(cursor.cur);

Now everything should be set, so let’s give it a spin. Of course, we want everything to be cross-browser. For the sake of testing open cursor.html in Internet Explorer, Firefox and (for those Mac lovers) Safari. Surprise, the cursor is the default one in IE and Mozilla, but it’s the desired one in Safari. Frustrating isn’t it? You write W3C compliant code and it doesn’t work in the first two major browsers. The “best” part is that this is happening for different reasons.

Let’s first take care of Mozilla. Remember from CSS2 specification that cursor property holds a list of possible cursors and the browser should use the first found one or the default one if none is found.
Add to this list default and modify the cursor property from

cursor: url(cursor.cur);


cursor: url(cursor.cur),default;

And now refresh the page in Firefox. Even tough it doesn’t make sense at all, it will work and you will see your nice cursor.

And now IE comes next (as it still doesn’t work). As you noticed in cursor.css, we used for the cursor property relative URIs. To quote from there: For CSS style sheets, the base URI is that of the style sheet, not that of the source document. But if you modify the cursor property to

cursor: url(cursor/cursor.cur),default;

this will actually work. This is because in IE, for style sheets, the base URI is that of the source element, not that of the style sheet. Totally opposite to W3C specifications, but, yeah … that’s MSIE.

And if we want to still work in Firefox and Safari we have to keep the property value as below:

cursor: url(cursor.cur),url(cursor/cursor.cur),default;

. So everytime you want to define a crossbrowser CSS cursor you should define it as a list containing the url relative to the source element, the url relative to the style sheet and the default value.

The above examples were tested on IE 6.0.2900.2180, IE 7.0.5730, Firefox, Firefox 3.0.1, Safari 3.0.4, all under Windows XP SP2. I also tested in Opera 9.25, but it seems that it doesn’t support custom cursors.

Later edit – Jan 28, 2009:
The above examples were also tested under Firefox 3.0.5, Internet Explorer 8 beta 2 (inside IETester), Internet Explorer 8 RC1 (version 8.0.6001.18372CO), Safari 3.2.1 (525.27.1), Google Chrome under Windows Vista.
I also tested with IE 5.5 (inside IETester), but it doesn’t support custom cursors.
There is also an example.

Later edit – Feb 10th, 2010:
If you want a custom cursor for an image (IMG) or link (A), then you need to attach the CSS to that tag, not to an enclosing container (e.g. DIV).