The CSS cursor Property
The cursor CSS property controls what the mouse pointer looks like when a user hovers over an element. It's one of those tiny yet impactful details that communicates affordance — it signals to the user what's interactive, what's draggable, what's resizable, and what's not.
Get it right and the interface feels intuitive. Get it wrong (using pointer everywhere, or forgetting to change the cursor on draggable elements) and users feel confused without being able to articulate why.
All Standard Cursor Values
The CSS spec defines over 30 cursor keyword values. Most developers know default, pointer, and not-allowed — but the full set is much richer:
General Interaction Cursors
| CSS Value | When to Use It |
|---|
default | The normal arrow cursor. Use for non-interactive page content. |
none | Hides the cursor entirely. Use sparingly — for fullscreen games or custom implementations. |
pointer | The hand with pointing finger. Use for clickable links and buttons. |
wait | The spinning wheel or hourglass. Signals the app is processing. |
progress | Like wait but indicates background processing — the user can still interact. |
not-allowed | A circle with a slash. Makes the "no" gesture clear for disabled elements. |
help | Arrow with a question mark. Use on elements with tooltips or help text. |
Text and Selection Cursors
| CSS Value | When to Use It |
|---|
text | The I-beam. Normally applied automatically to <input> and text nodes, but you may need it on custom elements. |
vertical-text | I-beam rotated 90°. For vertical text layouts common in East Asian typography. |
crosshair | Fine cross hairs. Use in color pickers, canvas drawing tools, or selection regions. |
Resize and Drag Cursors
| CSS Value | Direction |
|---|
n-resize | North (upward) resize |
s-resize | South (downward) resize |
e-resize | East (rightward) resize |
w-resize | West (leftward) resize |
ne-resize | Northeast (top-right) resize |
nw-resize | Northwest (top-left) resize |
se-resize | Southeast (bottom-right) resize |
sw-resize | Southwest (bottom-left) resize |
ew-resize | Bidirectional horizontal resize |
ns-resize | Bidirectional vertical resize |
nesw-resize | Diagonal bidirectional |
nwse-resize | Diagonal bidirectional |
col-resize | Column width adjustment |
row-resize | Row height adjustment |
all-scroll | Omni-directional scroll |
Drag and Drop Cursors
| CSS Value | Meaning |
|---|
grab | Item is grabbable (resting state) |
grabbing | Item is currently being grabbed/dragged |
move | Item can be moved |
copy | Indicates a copy operation |
alias | Indicates creating a shortcut or alias |
no-drop | Drop is not allowed at this location |
Zoom Cursors
| CSS Value | Meaning |
|---|
zoom-in | Magnifying glass with + |
zoom-out | Magnifying glass with − |
cell | Crosshair with plus, for spreadsheet cell selection |
context-menu | Arrow with menu indicator |
Custom Cursor Images
You can assign any image as a cursor using the url() syntax:
.custom-cursor {
cursor: url('/images/pencil-cursor.png') 0 16px, auto;
}
The two numbers after the URL are the hotspot coordinates — the exact pixel within the image that represents the cursor's active point. For a crosshair cursor, that's usually the center. For a pencil, it's typically the tip.
Best practices for custom cursors:
- Keep the image small — 32×32 pixels is the standard, 64×64 is the maximum many browsers support.
- Always provide a fallback cursor after the
url() (the auto at the end). If your image fails to load, the browser falls back to the standard cursor.
- PNG format with transparency works best.
- Avoid making the hotspot confusing — it should correspond to the "action point" of whatever the cursor represents.
Common Mistakes to Avoid
Using pointer on non-clickable elements. Only use pointer on elements that trigger an action on click. Using it too liberally confuses users about what's interactive.
Forgetting grabbing on drag start. If you apply grab on a draggable element, switch to grabbing when the drag begins. Without this, the cursor snaps back to grab mid-drag, looking jittery.
Not handling not-allowed on disabled buttons. A <button disabled> in HTML shows not-allowed by default — but custom buttons built with <div> elements don't. Always add cursor: not-allowed to visually disabled interactive elements.
Missing cursor on text over images. If you have text overlaid on a background image, browsers sometimes show the text cursor over the text and the pointer cursor when hovering the image behind it. Set cursor: default explicitly if needed.
Related Search Queries
To help users find exactly what they are looking for, this tool is also optimized for searches like: css mouse pointer, custom cursor test, css cursor hand.