Code Reference

Cursor

CSS · Reference cheat sheet

Cursor

CSS · Reference cheat sheet


📋 Overview

The cursor property sets the mouse pointer appearance when hovering an element. It communicates interactivity (links, drag handles, resize edges) and system state (loading, not-allowed). Use it to reinforce affordances already present in markup and behavior—never as the only signal that something is clickable.

Touch devices often ignore cursor styles; always pair with clear visual design and adequate hit targets.

🔧 Core concepts

Common keyword values

ValueTypical meaning
auto / defaultUA / arrow
pointerLink or button-like control
textSelectable text / inputs
moveDraggable item
grab / grabbingGrab affordance / active drag
not-allowedAction unavailable
wait / progressBusy (blocking vs background)
helpExtra information available
crosshairPrecise selection
zoom-in / zoom-outZoomable content

Resize & edge cursors

ValueDirection
n-resize s-resize e-resize w-resizeCardinal edges
ne-resize nw-resize se-resize sw-resizeCorners
col-resize / row-resizeColumn / row separators
ew-resize / ns-resize / nesw-resize / nwse-resizeBidirectional

Custom images

.canvas {
  cursor: url("/cursors/pen.svg") 4 4, crosshair;
}

Syntax: cursor: url(…) [x y], <fallback>. Hotspot coordinates are optional; always provide a keyword fallback.

💡 Examples

Interactive controls

a[href],
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]) {
  cursor: pointer;
}

button:disabled,
[aria-disabled="true"] {
  cursor: not-allowed;
}

Drag surface

.draggable {
  cursor: grab;
}

.draggable:active,
.draggable.is-dragging {
  cursor: grabbing;
}

Text vs chrome

.prose { cursor: auto; }
.prose code { cursor: text; }

.toolbar { cursor: default; }
.splitter { cursor: col-resize; }

Loading overlay

.page.is-loading,
.page.is-loading * {
  cursor: progress;
}

⚠️ Pitfalls

  • Setting cursor: pointer on non-interactive elements without keyboard/semantics support misleads users.
  • Omitting a fallback keyword after url() so broken custom cursors leave no pointer at all.
  • Using wait for long operations that still allow interaction—prefer progress when the UI remains usable.
  • Assuming cursor styles work on mobile; they usually don’t—design for touch without relying on them.
  • Nesting conflicting cursors (* rules) so child controls never show pointer or text.

On this page