orrect Cursor on Active Elements

Every active element must have a set cursor on hover. And it should be cursor:pointer in most cases.

By active elements I mean links, buttons, selects, labels with checkboxes and radio buttons, and other similar elements.

Those elements should be¬†treated¬†as ‚Äúactive‚ÄĚ when clicking on¬†such element results in¬†any action. Thereby a¬†menu item for the current page, checked radio button or¬†disabled buttons or¬†links are not active elements, so¬†they shouldn‚Äôt have any change on¬†hover.

At first I thought it’s obvious, but then I found out there are a lot of developers who think otherwise. And I didn’t find any proper arguments against cursor:pointer for active elements after reading all their points of view.

In this article I’ll tell you my arguments at first, and then I’ll discuss all the arguments against my point of view, describing why those arguments hadn’t incline me from it.

enefits of using cursor:pointer

isual Feedback

For me the main profit from changed cursor is the visual feedback. Ideally every custom element should change its state on hover. However, in real life such state could be absent or wouldn’t differ much from the original state, or would happen with a transition. So there would be no feedback, or it would be not obvious.

But you surely would see when the cursor changes¬†‚ÄĒ this happens instantly and stable. The click that could follow the mouseover would be intuitive, otherwise the brain would need to¬†match the position of¬†the cursor with the element or¬†spot the element‚Äôs change and then find out if¬†it‚Äôs a¬†hover state over this element‚Äôs active area or¬†something else.

Changing of the cursor is the most natural, noticeable and obvious feedback you could easily add to any element. Of course, it’s not the best variant, but it’s cheap and easy. If you could add a distinct visual state on hover, then it would be even better.

elimitation of the active area

There are a lot of cases when you should hint to the users that they could click already. You could often want to increase the clickable area of different elements, like for small icons or for menu items placed near the window edges. In those cases adding a cursor on hover would help users to find out when they could click on an element.

In¬†some cases, when there are adjacent elements, the cursor wouldn‚Äôt be¬†enough to¬†tell which element is¬†hovered¬†‚ÄĒ in¬†those cases you should change the visual state of¬†those elements.

Anyway, if¬†you‚Äôd hint users when to¬†use any specific active element, users would know it¬†and it¬†would be¬†easier for them to¬†use the¬†UI next time¬†‚ÄĒ they‚Äôd need to¬†aim with less precision, because they‚Äôd know that active area of¬†an¬†element could be¬†bigger than it¬†can be¬†seen. And when they‚Äôd move the cursor they¬†could click right at¬†the moment the cursor would change. Otherwise, if¬†an¬†element don‚Äôt change its cursor on¬†hover, the users would need to¬†aim carefully to¬†hit the area of¬†a¬†small element like icon or¬†checkbox.

And I could argue if someone would say the active area of an element should be as big as its visual representation, but I’ll keep my arguments on this topic for another article.

rguments against changing the cursor

I¬†really did try, but hadn‚Äôt find any proper arguments against changing the cursor over the active elements. Most of¬†those arguments can be¬†described¬†as ‚ÄúDon‚Äôt break users‚Äô habits!‚ÄĚ

But you can’t treat the presence of habits as an argument. This means there was one of the possible solutions and it was either the only one there, either it was the best at the moment. The habit should be treated in its context, and in context of what would happen if we’d brake it. Would it be destructive in some way, or it would be just a matter of minor users’ discomfort?

Another fact is that not all of the habits are good. If we’d always stay with the users’ desires, the progress would stop. Often users become used to the things that only hinder them. A clear example of such bad habit are labels for checkboxes and radio buttons. Lazy developers didn’t bind them together for years, so users often don’t know what the labels could be actually clicked, so they spend their time and efforts trying to hit those little areas of those little controls even if the labels are clickable too. It’s a great example why you should not only bind the inputs with labels, but also tell users about it with all possible ways.

We¬†could divide the ‚Äúhabits arguments‚ÄĚ into different categories. I‚Äôd try to¬†answer the most frequently used arguments against the changing of¬†the cursor on¬†hover.

‚ÄúThe cursor doesn‚Äôt change in¬†users‚Äô OS‚ÄĚ

In¬†OS¬†the most used cursor is¬†just an¬†arrow. It¬†doesn‚Äôt change over most of¬†the system controls like buttons. However, the question¬†is ‚ÄúIs¬†this really good?‚ÄĚ Is¬†it¬†familiar? Yes. But is¬†it¬†usable and could it¬†be¬†better? I¬†often see how some desktop app is¬†not usable because¬†I need to¬†guess where to¬†click¬†‚ÄĒ there are no¬†signs of¬†active areas.

When we¬†are talking about desktop we¬†should also talk about games too. Unlike apps, games often have custom cursors that are changed over different¬†UI elements. In¬†comparison with modern games most of¬†the web apps feel like the old games with pixel-hunting¬†‚ÄĒ you have to¬†guess where to¬†click and where to¬†hover in¬†order to¬†do¬†something. However, recently the web apps tend to¬†use more cursors for different actions like drag-n-drop or¬†resize. But why then use the default cursor for buttons? cursor:pointer would fit great there. And when we‚Äôd look at¬†the checkboxes and radio buttons, then there should be¬†not only a¬†distinct visual hover state like changed background, but you shouldn‚Äôt forget to¬†set the cursor:default for them¬†‚ÄĒ that‚Äôs the cursor the desktop apps mostly use to select something. But if¬†selecting the checkbox or¬†radio button results in¬†a¬†UI change like expanding the accordion‚Äôs section, then the best cursor would be¬†a¬†pointer one¬†‚ÄĒ telling something would happen after you‚Äôd click.

Web apps are not the same as desktop apps, there are a lot of new patterns and UI elements there, so it’s time to think again and decide which habits to forget.

Ah, that’s another often used argument. When there were no web apps, there were only linked textual documents. The apps mostly didn’t have such links, so in browsers, to tell users what the HTML <a> is, there appeared underline, blue color and a pointer cursor. And as all the buttons and inputs were system controls, they inherited the default behavior with the default cursor.

Years passed and sites become more complex and UI-rich, designers created new controls and they often were just the links disguised as buttons and other elements. And in most cases nobody removed the links’ cursors. So if you’d look at the modern sites, most custom buttons would be actually links and would have cursor:pointer there.

In¬†fact, you should forget the ‚Äúpointer is¬†for links‚ÄĚ thing a¬†long ago.

Well, yeah¬†‚ÄĒ links are not buttons, and buttons are not links. But that doesn‚Äôt mean the behavior of¬†hover for links and buttons should differ.

Nobody would expect an¬†ability to¬†open something in¬†a¬†new tab from the button. In¬†each case both the links and the buttons would have their context where users could either await the link‚Äôs behavior, either they¬†would just use the control they¬†have. And it¬†really doesn‚Äôt matter which cursor the users would see¬†‚ÄĒ if¬†users would see a¬†cursor in¬†a¬†links‚Äô context, they¬†would treat it¬†as¬†a¬†link. But if¬†users won‚Äôt expect a¬†link, the button underneath would be¬†ok. If¬†users would like to¬†attach a¬†file, they¬†won‚Äôt need the link‚Äôs behavior. If¬†users would like to¬†send a¬†form, they¬†would just do¬†it, even if¬†there‚Äôd be¬†a cursor:pointer on¬†it, the users won‚Äôt go¬†away and won‚Äôt try to¬†open it¬†in¬†a¬†new window¬†‚ÄĒ they¬†already know how to¬†use search forms. The only place when the users would be¬†confused¬†‚ÄĒ if¬†you‚Äôd do¬†it¬†reverse: make a¬†button look like a¬†link¬†‚ÄĒ be¬†blue and underlined.

Further more¬†‚ÄĒ there are already a¬†lot of¬†links that don‚Äôt look like ones and other elements that are disguised as¬†links. Different dropdown handles, filters, cuts, closing icons, ‚Äúcancel‚ÄĚ links¬†‚ÄĒ a¬†lot of¬†sites have a¬†lot of¬†elements using different tags in¬†HTML for them and having this cursor:pointer. Why would then simple buttons or¬†selects have default cursor instead of¬†the one all other controls have?

There is a great example from one company’s service:

Active areas example

You could try to guess which marked elements are links, which are not; which have cursor:pointer, which don’t. What would happen when you’ll hover or click any of those elements? You can think for a while, and I’ll give you an answer later.

If¬†you‚Äôd say straightforwardly ‚Äúonly everything that have href must have a¬†cursor‚ÄĚ then a¬†lot of¬†confusing things could appear. For example, if¬†there would be¬†one element visually, but with different tags underneath (like bootstrap‚Äôs buttons are), then it¬†would be¬†strange and confusing if¬†there‚Äôd be¬†a¬†difference between the button made of <a> and <button>. So, I¬†hope everyone would agree that the cursor over every such element should be¬†consistent. And If¬†you‚Äôd make the default one, then it¬†would become really confusing, ‚Äôcause there could be¬†a¬†disabled state for this button and you would need to¬†spot the change of¬†the button‚Äôs background in¬†order to¬†know could it¬†be¬†pressed or¬†no. And then if¬†you‚Äôd remove the cursor:pointer from an¬†actual link it¬†won‚Äôt be¬†any better, so¬†the only proper way is¬†to¬†have cursor:pointer in¬†both cases.

We could find a lot of examples with buttons, links and their states would conflict with each other and the overall UX. Making the cursor:pointer to mark only actionable elements makes sense and won’t create any conflicts other than slight discomfort for some persons.

And let’s get back to one strange service:

Active areas example

So, what’s there?

  1. It’s the post’s permalink. Ok, it’s an actual link, there is an underline and a pointer on hover.

  2. Hey, it’s not a link, it’s just a text, not clickable at all.

  3. That’s pseudo-link, there is no actual link, but there is a hover state as the one on permalink: underline and pointer. Clicking here calls a dropdown to appear.

  4. Another control that behaves like link (changes color on hover and gets cursor:pointer), but there is no actual link. Again, dropdown on click.

  5. This icon is¬†not a¬†link and clicking on¬†it¬†does nothing, while the other parts of¬†the snippet¬†‚ÄĒ header and picture¬†‚ÄĒ are links.

  6. There are two links: userpic and username. They’re not connected and have their own hovers: pointer and an underline for username.

  7. It’s a pseudo-link, no href seen. And the underline on hover and pointer.

  8. Oh, a¬†button! A¬†custom button. But what‚Äôt that? No¬†pointer on¬†hover! And even more¬†‚ÄĒ hover brings the dropdown, I¬†feel like on¬†a¬†minefield there.

  9. So, the button was treated as¬†a ‚Äúsystem‚ÄĚ element, but what‚Äôs with checkbox? It¬†and its label have cursor:pointer. Wow.

So, what could I say? There is no even slight consistency and a lot of other UI mistakes. But hey, there is no cursor:pointer on a button! I wonder which excuses the developer have for this.

BTW it’s very interesting to look at different services in the search for consistency, almost no one is perfect, so you could often find things to think about and to criticise on.

‚ÄúBut the specs say‚Ķ‚ÄĚ

SelenIT brings another argument (in Russian): both the CSS2.1 spec and¬†the CSS3 Basic UI clearly that ‚Äúthe cursor is¬†a¬†pointer that indicates a¬†link‚ÄĚ. He¬†also gives a¬†link to¬†a¬†G√©rard¬†Talbot‚Äôs message, where he¬†declines a¬†change to¬†one of¬†the CSS2.1¬†tests. However, it¬†couldn‚Äôt be¬†an¬†argument for this issue¬†‚ÄĒ the context of¬†this message is¬†a¬†test for spec, and if¬†spec says something, then the test should cover only this.

In¬†specs it¬†is¬†only said the pointer is¬†supposed to¬†be¬†used for links, but it¬†don‚Äôt imply you can‚Äôt use it¬†for anything other than link. It¬†states the default use of¬†such cursor, nothing more. Moreover, I¬†think this part in¬†specs should be¬†changed to¬†something like ‚ÄúThe cursor is¬†a¬†pointer that indicates an¬†element that can be¬†clicked‚ÄĚ to¬†reflect modern state of¬†the web¬†‚ÄĒ ‚Äôcause the current statement is¬†come at¬†least from the year¬†1997 and a¬†lot of¬†things did happen since then.


Here is another, different from habit ones, argument. If there would be a lot of actionable elements, they say, the cursor would blink a lot when you’d move it here and there.

But that’s not a proper argument, it’s a pointer for one of another problems:

  1. Active elements could be placed not that close one to another. In that case it would be harder for users to hit those elements and there would be symptomatic flickering when you’d move the cursor from one such element to another. Ideally, those elements should have continuous active areas. And to delimit different elements in that case you should use the visual hover like changing background and not the cursorless gaps.

  2. Another problem¬†‚ÄĒ cluttered interface. If¬†you‚Äôd have whole page covered in¬†active elements, then¬†‚ÄĒ yeah¬†‚ÄĒ the cursor would change a¬†lot (however, it¬†already changes a¬†lot when you hover over text or¬†other static elements). When you have a¬†lot of¬†active areas, it¬†could be¬†that you need to¬†simplify something there.


In¬†ideal situation every active element should have a¬†distinct visual hover state. But even with such state it¬†won‚Äôt hurt to¬†add a cursor:pointer¬†‚ÄĒ it¬†would only add clarity and would remove possible¬†UI conflicts. And if¬†you can‚Äôt find how to¬†make a¬†visual state on¬†hover, adding pointer would be¬†enough for most cases (however, if¬†you‚Äôre working with a¬†designer, it¬†would be¬†better to¬†ask them to¬†give you a¬†correct visual hover state).

And there are just no other arguments against cursor over active elements than user habits. And there would be more happy users than those who moan.

However, if¬†you have any other arguments¬†I didn‚Äôt cover¬†‚ÄĒ I¬†would like to¬†hear them. If¬†you know of¬†any A/B-testing with different cursors¬†‚ÄĒ it¬†would be¬†very cool to¬†look at¬†the results of¬†those.

Anyway, I hope now this topic is obvious and you would go and add the cursor:pointer to anywhere on you page where it is needed.