Reference
CSS cursor: every value, with a live preview
The cursor property sets the pointer a reader sees over an element. Here are all 36 keywords and url(), grouped by what they tell the reader. Move your mouse over any row to see the cursor your browser draws for it.
Syntax
How the property works
/* A keyword */
button {
cursor: pointer;
}
/* Your own image: a hotspot (x y) and a keyword to fall back on */
.canvas {
cursor: url("pen.png") 4 28, crosshair;
}
Give cursor one keyword, or a list of images followed by one keyword. The browser uses the first image
it can load and show, and the keyword at the end is required: it is what readers see if no image works.
The two numbers after an image are its hotspot, the pixel that does the clicking, counted from the top-left corner. Leave them out and the browser uses the hotspot stored in the file if it has one (a .cur does), or the top-left pixel if it does not (a PNG or SVG).
Keep cursor images at 32 × 32 pixels where you can. Firefox and Chromium-based browsers will not show a cursor image larger than 128 × 128.
3 values
General
Let the browser decide, show the plain arrow, or show nothing at all.
5 values
Links and status
Clickable things, help, context menus, and waiting.
| Value | Try it | What it tells the reader |
|---|---|---|
context-menu | A context menu is available for whatever is under the pointer. | |
help | Help is available, usually an arrow with a question mark. | |
pointer | A link or something you can click, usually a pointing hand. | |
progress | Something is working in the background, but you can keep using the page. | |
wait | The page is busy and you have to wait before doing anything. |
4 values
Selection
Selecting text, table cells, and exact points.
| Value | Try it | What it tells the reader |
|---|---|---|
cell | A table cell, or a range of cells, can be selected. | |
crosshair | You can pick an exact point, as in a drawing or cropping tool. | |
text | Text can be selected, usually an I-beam. | |
vertical-text | Vertical text can be selected, usually an I-beam turned on its side. |
7 values
Drag and drop
Grabbing, moving, copying, and refusing a drop.
| Value | Try it | What it tells the reader |
|---|---|---|
alias | Dropping here makes a shortcut or alias to the item. | |
copy | Dropping here makes a copy of the item. | |
move | The item under the pointer can be moved. | |
no-drop | The item you are dragging cannot be dropped here. | |
not-allowed | The action you are trying will not happen. | |
grab | Something can be grabbed and dragged, usually an open hand. | |
grabbing | Something is being dragged right now, usually a closed hand. |
15 values
Resize and scroll
Edges, corners, columns, rows, and panning.
| Value | Try it | What it tells the reader |
|---|---|---|
all-scroll | The content can be scrolled or panned in any direction. | |
col-resize | A column can be made wider or narrower. | |
row-resize | A row can be made taller or shorter. | |
n-resize | The top (north) edge can be moved. | |
e-resize | The right (east) edge can be moved. | |
s-resize | The bottom (south) edge can be moved. | |
w-resize | The left (west) edge can be moved. | |
ne-resize | The top-right (north-east) corner can be moved. | |
nw-resize | The top-left (north-west) corner can be moved. | |
se-resize | The bottom-right (south-east) corner can be moved. | |
sw-resize | The bottom-left (south-west) corner can be moved. | |
ew-resize | Something can be resized to the left and right. | |
ns-resize | Something can be resized up and down. | |
nesw-resize | Something can be resized along the top-right to bottom-left diagonal. | |
nwse-resize | Something can be resized along the top-left to bottom-right diagonal. |
1 values
Custom images
Your own image, with a hotspot and a fallback keyword.
| Value | Try it | What it tells the reader |
|---|---|---|
url() | Your own image as the cursor, with an optional hotspot and a keyword to fall back on. |
Custom images
Custom cursor images, browser by browser
Every desktop browser accepts custom cursor images. Keep them at 32x32, end the list with a keyword, and expect the fallback near the edges of the page.
Support
| Browser | Engine | url() from version | Hotspot numbers from version | Uses the hotspot in a .cur file |
|---|---|---|---|---|
| Chrome | Blink | 1 | 1 | Yes |
| Edge | Blink | 12 | 12 | Yes |
| Firefox | Gecko | 1.5 | 1.5 | Yes |
| Safari (macOS) | WebKit | 3 | 3 | Yes |
| Safari on iPad | WebKit | 13.4 | No | Not tested |
| Chrome for Android | Blink | 18 | 18 | Not tested |
Image formats
| Browser | PNG | SVG | .cur | GIF | .ani | Other formats |
|---|---|---|---|---|---|---|
| Chrome | Yes | Yes, needs a natural size (width and height) | Yes, including the hotspot stored in the file | Yes, first frame only (no animation) | No | Any still image format Chrome displays elsewhere, such as JPEG and WebP. |
| Edge | Yes | Yes, needs a natural size (width and height) | Yes, including the hotspot stored in the file | Yes, first frame only (no animation) | No | Same as Chrome. |
| Firefox | Yes | Yes, needs a natural size (width and height) | Yes, including the hotspot stored in the file | Yes, first frame only (no animation) | No | Any still image format Firefox displays elsewhere, such as JPEG and WebP. |
| Safari (macOS) | Yes | Yes | Yes, including the hotspot stored in the file (not in Lockdown Mode) | Yes, first frame only (no animation) | No | TIFF, BMP, ICO, JPEG and WebP. In Lockdown Mode only PNG, JPEG, GIF and WebP load. |
| Safari on iPad | Yes | Not tested | Not tested | Not tested | No | Not tested. |
| Chrome for Android | Yes | Not tested | Not tested | First frame only (not tested) | No | Not tested. |
Size limits
| Browser | Largest image | Near the edges of the page |
|---|---|---|
| Chrome | 128x128 CSS pixels. Larger images are skipped. | From Chrome 156, any custom cursor that would stick out of the visible page is skipped and the next value is used. Chrome 75 to 155 applied this only to images larger than 32x32. |
| Edge | 128x128 CSS pixels, as in Chrome. | Follows Chrome: from version 156 any custom cursor that would stick out of the visible page is skipped; earlier versions skipped only images larger than 32x32. |
| Firefox | 128x128 CSS pixels, per MDN. | Since Firefox 67, a cursor larger than 32x32 CSS pixels is skipped when it would stick out of the page's viewport (the layout.cursor.block.max-size setting, 32 by default). Cursors of 32x32 or smaller are never skipped for this reason. |
| Safari (macOS) | 128x128 CSS pixels. Larger images are skipped. | Any custom cursor that would not fit entirely inside the visible page is skipped, whatever its size. |
| Safari on iPad | Not documented. | Not documented. |
| Chrome for Android | Not documented; assume the desktop Chrome limit of 128x128. | Not documented; assume desktop Chrome behaviour. |
Which format to use
- PNG
- The safe default. Every desktop browser accepts it. Use 32x32 with a transparent background.
- SVG
- Sharp at any screen density. Give the root svg element width and height attributes; the spec only requires browsers to accept SVG cursors that state their own size.
- .cur
- The Windows cursor format. Browsers read it and use the hotspot stored inside, so you can leave out the coordinates in CSS.
- GIF
- Accepted, but every browser shows a single frame. An animated GIF does not animate as a cursor.
- .ani
- The Windows animated cursor format. No current browser accepts it in CSS; it is for installing on Windows.
Size advice
- 32x32 is the size to design for. It matches the default system cursor and avoids every edge rule.
- Anything above 128x128 is ignored by Chrome, Edge, Firefox and Safari.
- Between 33 and 128 pixels, Firefox and Chrome before 156 swap your cursor for the fallback near the edges of the page.
- From Chrome 156, and in Safari, any custom cursor is swapped for the fallback when it would stick out of the page, so keep the hotspot near the image's top-left if you want it to work right up to the edges.
The hotspot
- Syntax
url("file.png") X Y, keyword- Units
- Image pixels, measured from the top-left corner (0 0).
- Without numbers
- The hotspot stored in a .cur file, otherwise 0 0.
- Numbers outside the image
- Chrome and Firefox clamp values outside the image to its edges, as the spec asks. Safari ignores a hotspot outside the image and falls back to the hotspot stored in the file, or 0 0.
- On iPad
- Ignored on iPad.
Browser notes
- Chrome
-
- SVG cursors are drawn at the screen's pixel density, so they stay sharp.
- image-set() is accepted inside cursor for 1x and 2x files.
- Edge
-
- Edge 79 and later share Chrome's engine. Edge 12 to 18 used Microsoft's older engine.
- Firefox
-
- Hotspot coordinates are rounded and clamped to the image.
- Firefox 4 added url() cursors on macOS.
- Safari (macOS)
-
- An SVG without its own size is treated as 32x32.
- Safari on iPad
-
- Only applies to iPads with a trackpad or mouse. iPhones have no pointer.
- MDN's data lists hotspot coordinates as unsupported: the image is placed by its top-left corner.
- Chrome for Android
-
- Cursors only appear with a mouse or trackpad connected.
- Version numbers mirror desktop Chrome in MDN's data.
Sources
- MDN Web Docs: cursor
- CSS Basic User Interface Module Level 4: the cursor property
- MDN browser-compat-data: css.properties.cursor
- Chromium source: 128 px limit for web cursors (cursor.cc)
- Chromium commit: viewport containment for all custom cursors (Chrome 156)
- Firefox bug 1445844: block large cursors that cover browser UI
- WebKit source: image cursor selection (StyleCursor.cpp)
- WebKit source: cursor size limits (StyleCursorSizing.h)
- Chromium commit: removal of the 32 px exemption, shipped in Chrome 156 (chromiumdash)
- Firefox source: layout.cursor.block.max-size
- WebKit source: image types Safari loads, including Lockdown Mode
Checked 12 October 2026.
Windows and macOS
What each value becomes on Windows and macOS
Which system cursor each CSS keyword turns into. Windows names come from the registry and Mouse Properties; macOS names describe what Chrome asks macOS for. Safari and Firefox can differ on macOS.
- A Windows role
- Windows draws one of its 17 roles, so a custom Windows scheme changes it.
- Drawn by the browser
- Windows has no matching role; the browser draws its own image, and a Windows scheme cannot change it.
- Hidden
- No cursor is drawn.
- Your image
- Your own image.
| CSS value | Windows | Windows file | macOS | macOS cursor in code | Note |
|---|---|---|---|---|---|
auto | Normal Select(Arrow) | aero_arrow.cur | Arrow or I-beam | NSCursor.arrowCursor / NSCursor.IBeamCursor | Over selectable text the IBeam role is used instead. |
default | Normal Select(Arrow) | aero_arrow.cur | Arrow | NSCursor.arrowCursor | None |
none | Hidden | None | Hidden | (empty cursor) | None |
context-menu | Normal Select(Arrow) | aero_arrow.cur | Contextual menu | NSCursor.contextualMenuCursor | Windows has no context-menu cursor; Chrome, Edge and Firefox show the Arrow. |
help | Help Select(Help) | aero_helpsel.cur | Help | private system cursor | None |
pointer | Link Select(Hand) | aero_link.cur | Pointing hand | NSCursor.pointingHandCursor | None |
progress | Working in Background(AppStarting) | aero_working.ani | Busy but clickable | private system cursor | Animated on Windows. |
wait | Busy(Wait) | aero_busy.ani | Busy but clickable | private system cursor | Animated on Windows. Chrome on macOS shows the same cursor as progress. |
cell | Drawn by the browser | None | Cell | private system cursor | None |
crosshair | Precision Select(Crosshair) | built-in | Crosshair | NSCursor.crosshairCursor | None |
text | Text Select(IBeam) | built-in | I-beam | NSCursor.IBeamCursor | None |
vertical-text | Drawn by the browser | None | Vertical I-beam | NSCursor.IBeamCursorForVerticalLayout | None |
alias | Drawn by the browser | None | Drag link | NSCursor.dragLinkCursor | None |
copy | Drawn by the browser | None | Drag copy | NSCursor.dragCopyCursor | None |
move | Move(SizeAll) | aero_move.cur | Move | private system cursor | The look on macOS varies by browser. |
no-drop | Unavailable(No) | aero_unavail.cur | Operation not allowed | NSCursor.operationNotAllowedCursor | Drawn the same as not-allowed in Chrome, Edge and Firefox. |
not-allowed | Unavailable(No) | aero_unavail.cur | Operation not allowed | NSCursor.operationNotAllowedCursor | None |
grab | Drawn by the browser | None | Open hand | NSCursor.openHandCursor | None |
grabbing | Drawn by the browser | None | Closed hand | NSCursor.closedHandCursor | None |
all-scroll | Move(SizeAll) | aero_move.cur | Move | private system cursor | Chrome shows the move cursor on every platform; Firefox does on Windows. |
col-resize | Drawn by the browser | None | Column resize | NSCursor.columnResizeCursor (macOS 15+), NSCursor.resizeLeftRightCursor before | Closest Windows role: SizeWE. |
row-resize | Drawn by the browser | None | Row resize | NSCursor.rowResizeCursor (macOS 15+), NSCursor.resizeUpDownCursor before | Closest Windows role: SizeNS. |
n-resize | Vertical Resize(SizeNS) | aero_ns.cur | Resize up | frame resize cursor, top edge, outward (macOS 15+) | None |
e-resize | Horizontal Resize(SizeWE) | aero_ew.cur | Resize right | frame resize cursor, right edge, outward (macOS 15+) | None |
s-resize | Vertical Resize(SizeNS) | aero_ns.cur | Resize down | frame resize cursor, bottom edge, outward (macOS 15+) | None |
w-resize | Horizontal Resize(SizeWE) | aero_ew.cur | Resize left | frame resize cursor, left edge, outward (macOS 15+) | None |
ne-resize | Diagonal Resize 2(SizeNESW) | aero_nesw.cur | Resize up-right | frame resize cursor, top-right corner, outward (macOS 15+) | None |
nw-resize | Diagonal Resize 1(SizeNWSE) | aero_nwse.cur | Resize up-left | frame resize cursor, top-left corner, outward (macOS 15+) | None |
se-resize | Diagonal Resize 1(SizeNWSE) | aero_nwse.cur | Resize down-right | frame resize cursor, bottom-right corner, outward (macOS 15+) | None |
sw-resize | Diagonal Resize 2(SizeNESW) | aero_nesw.cur | Resize down-left | frame resize cursor, bottom-left corner, outward (macOS 15+) | None |
ew-resize | Horizontal Resize(SizeWE) | aero_ew.cur | Resize left-right | frame resize cursor, left edge, both ways (macOS 15+) | None |
ns-resize | Vertical Resize(SizeNS) | aero_ns.cur | Resize up-down | frame resize cursor, top edge, both ways (macOS 15+) | None |
nesw-resize | Diagonal Resize 2(SizeNESW) | aero_nesw.cur | Diagonal resize, top-right to bottom-left | frame resize cursor, top-right corner, both ways (macOS 15+) | None |
nwse-resize | Diagonal Resize 1(SizeNWSE) | aero_nwse.cur | Diagonal resize, top-left to bottom-right | frame resize cursor, top-left corner, both ways (macOS 15+) | None |
zoom-in | Drawn by the browser | None | Zoom in | NSCursor.zoomInCursor (macOS 15+) | None |
zoom-out | Drawn by the browser | None | Zoom out | NSCursor.zoomOutCursor (macOS 15+) | None |
url() | Your image | None | Your image | custom NSCursor from your image | None |
Windows roles no CSS value asks for:
Handwriting (NWPen)
, Alternate Select (UpArrow)
, Location Select (Pin)
and Person Select (Person)
. Browsers never show them; they are for desktop apps. The table of all 17 roles lists what each one is for.
Sources
- Chromium source: how Chrome maps CSS cursors to Windows cursors
- Chromium source: how Chrome maps CSS cursors to macOS cursors
- Chromium source: Blink cursor selection (event_handler.cc)
- MDN Web Docs: cursor
- Firefox bug 275173: no-drop shown as not-allowed
- Firefox bug 275174: all-scroll shown as move on Windows
Checked 12 October 2026.