PureDevTools

CSS Cursor Reference

Hover over all 36 CSS cursor values to see live previews — search, filter by category, copy CSS code, and generate custom url() cursors

All processing happens in your browser. No data is sent to any server.

Selected Cursor

Links & Status
Move mouse here to preview

cursor: pointer;

The cursor is a pointing hand, indicating a link or clickable element.

Use Case

Hyperlinks, buttons, interactive cards — any clickable element

CSS

.element {
  cursor: pointer;
}

Tip: click any cursor card to select and copy its CSS.

Custom Cursor via url()

Use any image URL as a cursor. A fallback keyword is required in case the image fails to load.

Generated CSS

.element {
  cursor: url("https://example.com/cursor.png") 0 0, default;
}

Requirements: Cursor images should be 32×32px (max 128×128px). Supported formats: PNG, SVG, GIF, .cur, .ani. The fallback keyword is mandatory — browsers ignore the rule if no fallback is provided.

All Cursors by Category

General

Links & Status

Selection

Drag & Drop

Resizing

Zooming

Your drag-and-drop interface uses cursor: pointer for everything — draggable items, resize handles, clickable buttons, text links. Users can’t tell what will happen before they click because every interaction looks the same. CSS has 36 cursor values (grab, col-resize, zoom-in, not-allowed, crosshair…) but nobody remembers more than five, and the only way to see what they look like is to write CSS and hover.

Why This Tool (Not MDN’s List)

MDN lists all cursor values with descriptions, but you can’t see what each cursor looks like without applying the CSS to an element and hovering. This reference shows all 36 cursor types as hoverable tiles — move your mouse over each one to see the actual cursor change in real time. Click to copy the CSS. Everything runs in your browser.

What Is the CSS cursor Property?

The CSS cursor property sets the type of cursor the browser should display when the mouse pointer is over an element. Choosing the right cursor communicates intent — it tells users what will happen before they click, drag, or resize.

.clickable {
  cursor: pointer;
}

.loading {
  cursor: wait;
}

.draggable {
  cursor: grab;
}

.draggable:active {
  cursor: grabbing;
}

All CSS cursor Values

The cursor property accepts 36 keyword values grouped into six functional categories, plus the special url() function for custom cursors.

General Cursors

ValueAppearanceWhen to Use
autoBrowser decidesDefault — browser infers from element type
defaultArrow pointerExplicit default arrow, reset from other cursors
noneHiddenCustom cursor overlays, kiosk touch interfaces
context-menuArrow + menuElements with right-click context menus
helpArrow + ?Tooltip targets, help icons, documentation
ValueAppearanceWhen to Use
pointerPointing handLinks, buttons, any clickable element
progressArrow + spinnerBackground processing (user can still interact)
waitSpinner/hourglassBlocking operation (user must wait)

The distinction between progress and wait is important: progress should be used when users can still click and interact with the page during a background process. wait is for blocking operations where the browser is unresponsive.

Selection Cursors

ValueAppearanceWhen to Use
cellLarge crosshairSpreadsheet cells, table selection
crosshairThin crosshairImage editors, canvas tools, map coordinates
textI-beam (horizontal)Selectable or editable horizontal text
vertical-textI-beam (vertical)Vertical text in CJK writing modes

Drag & Drop Cursors

ValueAppearanceWhen to Use
aliasArrow + shortcut badgeCreating shortcuts or symbolic links
copyArrow + plus badgeDrop targets where item will be copied
moveFour-directional arrowDraggable elements (in transit)
no-dropArrow + no circleInvalid drop target
not-allowedCircle with slashDisabled actions, restricted areas
grabOpen handDraggable element (idle, can grab)
grabbingClosed handDraggable element (currently being dragged)

Always pair grab and grabbing in your CSS: apply grab by default and switch to grabbing on mousedown or :active.

.draggable-card {
  cursor: grab;
}

.draggable-card:active {
  cursor: grabbing;
}

Resize Cursors

The 15 resize cursors cover single-direction and bidirectional resize handles, using compass directions:

Single-direction (n, e, s, w, ne, nw, se, sw): drag moves a single edge or corner in that direction.

Bidirectional (ew-resize, ns-resize, nesw-resize, nwse-resize): double-headed arrows indicate the element can be resized in either direction along that axis.

Utility resize cursors:

/* Resizable panel with directional handles */
.resize-handle-right    { cursor: e-resize; }
.resize-handle-bottom   { cursor: s-resize; }
.resize-handle-corner   { cursor: se-resize; }
.resize-handle-col      { cursor: col-resize; }

Zoom Cursors

ValueAppearanceWhen to Use
zoom-inMagnifier + plusContent can be zoomed in (maps, images)
zoom-outMagnifier + minusContent can be zoomed out (already zoomed state)

Custom Cursors with url()

Beyond the keyword values, the cursor property accepts a url() function that points to an image file. A fallback keyword value must be provided after the URL in case the custom cursor fails to load.

.custom {
  /* x y hotspot offsets are optional (defaults to 0 0) */
  cursor: url("/cursors/my-cursor.png") 16 16, pointer;
}

Cursor image requirements:

Always provide a fallback:

/* WRONG — no fallback, cursor disappears if image fails */
.bad { cursor: url("/my-cursor.png"); }

/* CORRECT — fallback keyword after the url() */
.good { cursor: url("/my-cursor.png") 0 0, default; }

/* Multiple fallbacks (first that works wins) */
.multi { cursor: url("/a.cur"), url("/a.png") 0 0, pointer; }

Cursor Priority and Inheritance

The cursor property inherits from the parent element. The browser resolves the cursor from the innermost element outward until a non-auto value is found:

/* Parent defines wait, but child overrides with pointer */
.loading-overlay { cursor: wait; }
.loading-overlay .cancel-btn { cursor: pointer; /* overrides wait */ }

Accessibility Considerations

Cursor types convey meaning to sighted users, but they are invisible to keyboard-only users and screen reader users. Always supplement cursor changes with:

  1. ARIA attributes: Use aria-disabled="true" for not-allowed, aria-busy="true" for wait/progress
  2. Visual indicators: Don’t rely on cursor alone to indicate state (add opacity, color, or text labels)
  3. Focus styles: Ensure all interactive elements have visible :focus styles independent of cursor
/* Combine cursor with visual disabled state */
button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

Browser Support

All 36 keyword cursor values have excellent support across modern browsers (Chrome, Firefox, Safari, Edge). The grab and grabbing values required the -webkit- prefix in older WebKit browsers but are now unprefixed in all modern browsers.

Custom url() cursors are supported in all modern browsers, though behavior on HiDPI/Retina displays varies — providing @2x variants or SVG cursors is recommended for crisp display on high-density screens.

FAQ

What is the difference between cursor: default and cursor: auto?

cursor: auto delegates the cursor choice to the browser based on context — the browser shows an I-beam over selectable text, a pointer over links, and an arrow elsewhere. cursor: default always shows the platform’s default arrow cursor, regardless of context. Use auto to let the browser make smart decisions; use default to explicitly override back to the arrow.

When should I use cursor: wait vs cursor: progress?

Use cursor: wait for blocking operations where the entire page is unresponsive (e.g., a full-page synchronous operation). Use cursor: progress when something is loading in the background but the user can still scroll, click elsewhere, or interact with other parts of the page. This semantic difference helps users understand whether they need to pause or can continue working.

Why does cursor: none hide the cursor?

cursor: none removes the system cursor entirely from the element. This is useful when you’ve built a fully custom cursor using JavaScript and CSS (e.g., a large glowing circle following the mouse) and don’t want the system cursor to overlap it. Always ensure usability and accessibility when hiding the cursor.

Can I use SVG as a custom cursor?

Yes, modern browsers support SVG in url() cursor references. SVGs scale perfectly on HiDPI displays, making them the best format for custom cursors. Note that inline SVG (data URIs) also work: cursor: url("data:image/svg+xml,...") 0 0, default;.

What is the hotspot in a custom cursor?

The hotspot is the pixel coordinate within the cursor image that acts as the actual pointer tip — the precise point where clicks are registered. For a default arrow, the hotspot is typically 0 0 (top-left). For a crosshair, it would be the center. Specify hotspot as the second argument pair after url(): cursor: url("crosshair.png") 16 16, crosshair;.

Related Tools

More CSS Tools