Use CSS to Change the Mouse Cursor

Image by Liam Briese.

Changing the mouse cursor is a pretty simple task. If you were online in the nineties or early noughties, you probably became very familiar with sparkly, blinking, custom cursors on every other website you visit. Maybe you even downloaded some of those custom cursors and the spyware, adware, and malware that came with them. I personally was very pleased with the animated, trailing clock I managed to implement into a site I maintained at the time.

However, aside from being a bad memory from my misguided youth on the web, there are actually useful and surprisingly common use cases for changing the mouse cursor on the modern web. It's also easy enough, with some handy and widelysupported CSS rules to take care of it.


The Sensible Choice.

Native form controls should be the first choice. If a custom dropdown is genuinely necessary, start with a <button> trigger and implement the required semantics, keyboard behaviour, focus management, and accessible name.

The cursor is only a visual cue; it cannot make a custom control behave like a native select. Use cursor: pointer only after the element is operable and understandable with a keyboard and assistive technology.

For example, you could use something like this simple snippet:

.dropdown-button {  cursor: pointer;}

Fairly straightforward, right? The pointer value is one of a set of default values available through CSS, the full collection being:

autodefaultnonecontext-menuhelppointerprogresswaitcellcrosshairtextvertical-textaliascopymoveno-dropnot-allowedall-scrollcol-resizerow-resizen-resizee-resizes-resizew-resizens-resizeew-resizene-resizenw-resizese-resizesw-resizenesw-resizenwse-resize

These will render similarly across browsers and on different systems using operating system defaults. For instance, in Chrome on Mac, not-allowed & no-drop are the same, amongst some of the others.

This set of cursor options will probably cover basically any user experience situation that you find yourself in. Honestly, you probably won't even be using the vast majority of them at any point in your career (I can't recall a time I've ever used all-scroll, for instance).

It is important to remember, though, when you're making the decision to change the cursor, that you are affecting a crucial piece of the UX. You need to make sure that you are choosing the right cursor for the job and make sure that you have a good reason to change it; otherwise, your users could be left confused and a bit lost.

Avoid changing the cursor simply to suppress the textselection affordance. A decorative heading still needs to remain readable and selectable unless there is a specific usability reason to do otherwise.



The (Possibly) LessSensible Choice.

A custom image cursor can be decorative, but it must not be the only indication that something is interactive. Preserve the platform fallback and make sure controls still look, focus, and behave like controls without the custom image.

The cursor property can also accept image URLs as a value, meaning you could use a .png or .svg (amongst other formats). Always provide a standard cursor fallback because custom images can fail to load or be unsupported. At the time of writing, SVG could be difficult to display in Chrome on a Mac.

I have personally used image cursors on a few occasions. The testimonials carousel in my website footer used stylised SVG arrows, but carousel controls must remain visible and keyboardfocusable; a cursor cannot replace them. Another example is the IMG Licensing website I put together last year. Their new branding featured contemporary plus symbols, so it made sense to include that sparingly into the new site.

The cursor: none; value removes the platform pointer altogether. Do not use it across an interactive page: a JavaScript replacement can fail, does not help touch or keyboard users, and can hide a familiar orientation cue. The Pantheone Audio website was an example of that visual treatment: cursor: none; has been declared on body to hide the default pointer. That is historical observation, not a recommendation to copy the pattern.

If you use a custom cursor, treat it as a secondary visual enhancement. Keep the standard fallback, preserve native control semantics, retain visible focus and controls, and never rely on the cursor alone to communicate an action.


Need a senior engineer involved?

I can work directly in the codebase, review the architecture, or support the team through delivery when the work needs more than extra hands.