Cursor
Cursor utilities set the cursor property: the pointer shown when a mouse hovers an element. Each class is named after its CSS value: cursor-pointer is cursor: pointer.
How cursor works
Section titled “How cursor works”- One class per value.
cursor-{value}for 32 standard CSS cursor values. There is no configuration map and no token. - Mouse only. Cursors appear only for mouse and other fine pointers. Touch screens show no cursor, so a cursor must never be the only sign that something is interactive.
Values
Section titled “Values”| Group | Classes |
|---|---|
| General | cursor-auto, cursor-default, cursor-none |
| Links and status | cursor-pointer, cursor-help, cursor-context-menu, cursor-progress, cursor-wait, cursor-not-allowed |
| Selection | cursor-text, cursor-cell, cursor-crosshair |
| Drag and drop | cursor-move, cursor-grab, cursor-grabbing, cursor-all-scroll |
| Zoom | cursor-zoom-in, cursor-zoom-out |
| Resize | cursor-col-resize, cursor-row-resize, cursor-n-resize, cursor-e-resize, cursor-s-resize, cursor-w-resize, cursor-ne-resize, cursor-nw-resize, cursor-se-resize, cursor-sw-resize, cursor-ew-resize, cursor-ns-resize, cursor-nesw-resize, cursor-nwse-resize |
Hover each box to see its cursor:
<div class="flex wrap gap-2"> <div class="cursor-pointer p-3 bg-alternate rounded">pointer</div> <div class="cursor-help p-3 bg-alternate rounded">help</div> <div class="cursor-not-allowed p-3 bg-alternate rounded">not-allowed</div> <div class="cursor-wait p-3 bg-alternate rounded">wait</div> <div class="cursor-progress p-3 bg-alternate rounded">progress</div> <div class="cursor-text p-3 bg-alternate rounded">text</div> <div class="cursor-crosshair p-3 bg-alternate rounded">crosshair</div> <div class="cursor-move p-3 bg-alternate rounded">move</div> <div class="cursor-grab p-3 bg-alternate rounded">grab</div> <div class="cursor-grabbing p-3 bg-alternate rounded">grabbing</div> <div class="cursor-zoom-in p-3 bg-alternate rounded">zoom-in</div> <div class="cursor-col-resize p-3 bg-alternate rounded">col-resize</div></div>.card-link { @include apply(cursor(pointer));}.splitter { @include apply(cursor(col-resize));}Common patterns
Section titled “Common patterns”cursor-pointeron a custom clickable element that is not a link or button, such as a whole card that links somewhere. Native links already show the pointer.cursor-not-allowedon a disabled control, together with thedisabledattribute oraria-disabled="true".cursor-grabon a draggable handle at rest, andcursor-grabbingwhile it is dragged (add the class from your drag code).cursor-col-resizeandcursor-row-resizeon splitter bars between panes.cursor-waitwhile the whole page is blocked;cursor-progresswhile work continues in the background and the page is still usable.
<div class="flex wrap gap-3 x-center"> <button type="button" disabled class="cursor-not-allowed">Disabled</button> <div class="cursor-grab p-3 border border-dashed rounded">Drag handle</div></div>Responsive and state variants
Section titled “Responsive and state variants”Cursor classes have no responsive and no state variants. A cursor already shows only on hover, so a hover: form is not needed. To change the cursor in a state, use the mixin with a state modifier:
.row { @include apply(cursor(default), cursor(pointer) hover);}cursor() writes its argument as is, so it accepts any CSS cursor value, including image cursors with a fallback.
@use "@nuvoui/core" as *;
.card-link { @include apply(cursor(pointer));}.canvas { @include apply(cursor((url("/cursors/pen.svg") 4 4, crosshair)));}.card-link { cursor: pointer;}.canvas { cursor: url("/cursors/pen.svg") 4 4, crosshair;}cursor() does not validate its value; a misspelled value is emitted as written and ignored by the browser. cursor() takes one argument, so wrap a value that contains commas, such as an image with a fallback, in parentheses: cursor((url(...) 4 4, crosshair)). Without them Sass reports Only 1 argument allowed, but 2 were passed.
Configuration
Section titled “Configuration”The list of cursor classes is fixed. Turn the classes off with the cursors feature flag; the mixin stays available. A flag missing from your $feature-flags map counts as on, so the map below turns off cursor classes only.
@use "@nuvoui/core" with ( $generate-utility-classes: true, $feature-flags: ("cursors": false));Class reference
Section titled “Class reference”Generated from the compiled core build.
Cursor (32 rules)
| Selector | Declarations | Default value |
|---|---|---|
.cursor-auto | cursor: auto | auto |
.cursor-pointer | cursor: pointer | pointer |
.cursor-default | cursor: default | default |
.cursor-move | cursor: move | move |
.cursor-not-allowed | cursor: not-allowed | not-allowed |
.cursor-wait | cursor: wait | wait |
.cursor-help | cursor: help | help |
.cursor-text | cursor: text | text |
.cursor-cell | cursor: cell | cell |
.cursor-crosshair | cursor: crosshair | crosshair |
.cursor-grabbing | cursor: grabbing | grabbing |
.cursor-grab | cursor: grab | grab |
.cursor-zoom-in | cursor: zoom-in | zoom-in |
.cursor-zoom-out | cursor: zoom-out | zoom-out |
.cursor-none | cursor: none | none |
.cursor-progress | cursor: progress | progress |
.cursor-col-resize | cursor: col-resize | col-resize |
.cursor-row-resize | cursor: row-resize | row-resize |
.cursor-n-resize | cursor: n-resize | n-resize |
.cursor-e-resize | cursor: e-resize | e-resize |
.cursor-s-resize | cursor: s-resize | s-resize |
.cursor-w-resize | cursor: w-resize | w-resize |
.cursor-ne-resize | cursor: ne-resize | ne-resize |
.cursor-nw-resize | cursor: nw-resize | nw-resize |
.cursor-se-resize | cursor: se-resize | se-resize |
.cursor-sw-resize | cursor: sw-resize | sw-resize |
.cursor-ew-resize | cursor: ew-resize | ew-resize |
.cursor-ns-resize | cursor: ns-resize | ns-resize |
.cursor-nesw-resize | cursor: nesw-resize | nesw-resize |
.cursor-nwse-resize | cursor: nwse-resize | nwse-resize |
.cursor-context-menu | cursor: context-menu | context-menu |
.cursor-all-scroll | cursor: all-scroll | all-scroll |
Accessibility and RTL
Section titled “Accessibility and RTL”- Cursor is not semantics.
cursor-pointeron adivdoes not make it a button. Use a realbuttonoraelement so keyboard and screen reader users can reach and operate it (WCAG 4.1.2 Name, Role, Value). - Do not hide the cursor without a replacement.
cursor-noneis for media players and canvases that draw their own pointer. - Touch. Touch devices show no cursor; disabled and draggable states also need a visible style.
- RTL. Cursor values are not mirrored by the browser.
cursor-e-resizepoints right in both directions; for a handle on the inline end side, choose the cursor in your SCSS from the direction if needed.