The Basic Syntax
.element {
cursor: url('my-cursor.png'), pointer;
}
A custom cursor references an image with url(), followed by a comma and a mandatory keyword fallback — the fallback is not optional; a plain url() with no keyword afterward is invalid syntax.
Setting the Hotspot
.element {
cursor: url('my-cursor.png') 4 12, pointer;
}
The two numbers after the URL are the hotspot coordinates — the exact x and y pixel position within the image that counts as the actual click point. They're measured in image pixels from the image's top-left corner. If omitted, the browser may read hotspot data from the image file's own metadata, or default to the top-left corner if none is available.
Multiple Fallback Images
.element {
cursor: url('cursor.svg'), url('cursor.png') 4 4, url('cursor.cur') 5 5, pointer;
}
The browser tries each image in order, moving to the next if the current one can't be loaded or isn't a supported format, and only falls back to the final keyword if none of the images load at all.
Recommended Image Sizing
32×32 or 48×48 pixels are the commonly recommended cursor image sizes — larger images may not be consistently supported across every browser.
Should You Even Use a Custom Cursor?
A custom cursor should still visually communicate the same kind of interaction a built-in keyword would — using an unrelated or purely decorative image in place of a standard cursor can genuinely confuse users about what an element actually does. Reach for a custom cursor when it reinforces a specific interaction clearly, not simply as a stylistic flourish.
Ready to build a custom cursor with the correct syntax?
Open CSS Cursor Generator