223

I have a JavaScript webapp where the user needs to grab the background to move the whole screen around. So I want the cursor to change when they're hovering over the background. The -moz-grab and -moz-grabbing CSS cursors are ideal for this. Of course, they only work in Firefox... are there equivalent cursors for other browsers? Do I have to do something a little more custom than standard CSS cursors?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
at.
  • 50,922
  • 104
  • 292
  • 461

7 Answers7

553

In case anyone else stumbles across this question, this is probably what you were looking for:

.grabbable {
    cursor: move; /* fallback if grab cursor is unsupported */
    cursor: grab;
    cursor: -moz-grab;
    cursor: -webkit-grab;
}

 /* (Optional) Apply a "closed-hand" cursor during drag operation. */
.grabbable:active {
    cursor: grabbing;
    cursor: -moz-grabbing;
    cursor: -webkit-grabbing;
}
vallentin
  • 23,478
  • 6
  • 59
  • 81
J.Steve
  • 7,109
  • 2
  • 22
  • 22
  • 54
    for some reason the 'grabbing' only appears when i release the mouse. any idea why this is? – Jona Jun 13 '16 at 09:56
  • @Jona my guess is that you didn't add the `grabbable` class to any element which can be grabbed, and you're toggling the class when they're being dragged. – Emile Bergeron Jul 15 '16 at 20:13
  • 2
    nice extended answer, thanks for adding the extra "grabbing" bit. nice touch. :) – scotself Aug 19 '16 at 20:34
  • 2
    For anyone having trouble with this solution, I had to set the `grab` cursor on `:hover` rather than the plain selector, i.e. `.grabbable:hover` in the example above. – Markus Amalthea Magnuson Oct 25 '16 at 10:15
  • @Jona adding these styles to the parent `
      ` instead of `
    • ` in my case solved the issue
    – Arthur Tarasov Jul 17 '17 at 10:24
  • @Jona Did you ever find a solution to that? – Jesper Nov 08 '17 at 04:11
  • @Jesper i think it's the browser's issue. If you hard refresh your page in new tab it can be temporarily fixed. (i'm using chrome). – Exil Nov 24 '17 at 10:22
  • @ExillustX even hard refreshing does not solved the problem , any solution yet ????? – amdev Aug 25 '18 at 18:37
  • Re: '`grabbing`' only appears when i release the mouse. -> For my scenario, in angular I was able to remove the style, then set it to `grabbing` and works as expected.. As opposed to just updating it. – ttugates Feb 21 '19 at 21:46
  • @Jona and others, apply `grab` on `:hover` like @Markus suggested, it worked for me. Maybe it makes sense to update the answer? – waterplea Dec 02 '21 at 07:59
138

I think move would probably be the closest standard cursor value for what you're doing:

move
Indicates something is to be moved.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 1
    I saw the move icon, thought the grab icon was better. But now that you pointed out w3c considers that cursor "Indicates something is to be moved," it makes the most sense. Thanks. – at. Apr 18 '11 at 07:05
  • 2
    @at: You can specify multiple cursors in a comma-delimited list and the user agent should use the first one it understands. So you can use the -moz* ones and "move" as a fallback. – mu is too short Apr 18 '11 at 07:15
  • 18
    @muistooshort are you sure a comma-list still works? I'm using `cursor:move; cursor:-webkit-grab; cursor:-moz-grab; cursor:grab;` with most preferred last. – Bob Stein Jul 19 '13 at 21:09
  • 2
    @BobStein-VisiBone: I think there could have been some confusion up there a couple years ago. AFAIK the comma-list works if you're specifying multiple *formats* like [`cursor: url(example.svg#linkcursor), url(hyper.cur), pointer`](http://www.w3.org/TR/CSS21/ui.html#propdef-cursor) rather than multiple possible values. I think you're approach might be necessary. – mu is too short Jul 19 '13 at 21:41
61

CSS3 grab and grabbing are now allowed values for cursor. In order to provide several fallbacks for cross-browser compatibility3 including custom cursor files, a complete solution would look like this:

.draggable {
    cursor: move; /* fallback: no `url()` support or images disabled */
    cursor: url(images/grab.cur); /* fallback: Internet Explorer */
    cursor: -webkit-grab; /* Chrome 1-21, Safari 4+ */
    cursor:    -moz-grab; /* Firefox 1.5-26 */
    cursor:         grab; /* W3C standards syntax, should come least */
}

.draggable:active {
    cursor: url(images/grabbing.cur);
    cursor: -webkit-grabbing;
    cursor:    -moz-grabbing;
    cursor:         grabbing;
}

Update 2019-10-07:

.draggable {
    cursor: move; /* fallback: no `url()` support or images disabled */
    cursor: url(images/grab.cur); /* fallback: Chrome 1-21, Firefox 1.5-26, Safari 4+, IE, Edge 12-14, Android 2.1-4.4.4 */
    cursor: grab; /* W3C standards syntax, all modern browser */
}

.draggable:active {
    cursor: url(images/grabbing.cur);
    cursor: grabbing;
}
Volker E.
  • 5,911
  • 11
  • 47
  • 64
  • 2
    Your post is a duplicate of J.Steve's –  Sep 22 '16 at 05:41
  • 11
    @user2230470 It is different in two important points: First, it provides an cursor image for the browsers not supporting `grab`, but cursor images. Second, it's best practice to have standards syntax *after* the vendor prefixed values. – Volker E. Sep 30 '16 at 18:15
  • really?! how come? also, where can i find more info about standard practices akin to such. –  Oct 02 '16 at 02:29
  • 9
    @user2230470 - because in cases where a browser supports 2 behaviors where the prefixed one may have been implemented slightly before the finalization of the standard one (and therefore may act differently) you want it to use the standard one...and whatever definition comes LAST is the one the browser will use. Therefore the standard one should go last. – Jimbo Jonny Oct 31 '16 at 15:15
  • 3
    is `images/grab.cur` an example URL for an image that I need to host on my web server, or is that some magic IE thing? – jrz Aug 12 '17 at 02:48
  • @Jonz It's an example URL, but be aware that IE and Edge just support .cur and .ani format, see https://msdn.microsoft.com/en-us/library/aa358795.aspx – Volker E. Aug 14 '17 at 19:54
  • Should you add a `cursor: move` as a fallback for `:active` or is it not needed? – new name Aug 23 '17 at 16:18
  • @JeffO'Neill No need because :active is come after .draggable {...} When there is no cursor it will use the cursor inherit from the class before. – vee Dec 04 '17 at 11:32
26

"more custom" than CSS cursors means a plugin of some type, but you can totally specify your own cursors using CSS. I think this list has what you want:

.alias {cursor: alias;}
.all-scroll {cursor: all-scroll;}
.auto {cursor: auto;}
.cell {cursor: cell;}
.context-menu {cursor: context-menu;}
.col-resize {cursor: col-resize;}
.copy {cursor: copy;}
.crosshair {cursor: crosshair;}
.default {cursor: default;}
.e-resize {cursor: e-resize;}
.ew-resize {cursor: ew-resize;}
.grab {cursor: grab;}
.grabbing {cursor: grabbing;}
.help {cursor: help;}
.move {cursor: move;}
.n-resize {cursor: n-resize;}
.ne-resize {cursor: ne-resize;}
.nesw-resize {cursor: nesw-resize;}
.ns-resize {cursor: ns-resize;}
.nw-resize {cursor: nw-resize;}
.nwse-resize {cursor: nwse-resize;}
.no-drop {cursor: no-drop;}
.none {cursor: none;}
.not-allowed {cursor: not-allowed;}
.pointer {cursor: pointer;}
.progress {cursor: progress;}
.row-resize {cursor: row-resize;}
.s-resize {cursor: s-resize;}
.se-resize {cursor: se-resize;}
.sw-resize {cursor: sw-resize;}
.text {cursor: text;}
.url {cursor: url(https://www.w3schools.com/cssref/myBall.cur),auto;}
.w-resize {cursor: w-resize;}
.wait {cursor: wait;}
.zoom-in {cursor: zoom-in;}
.zoom-out {cursor: zoom-out;}
<h1>The cursor Property</h1>
<p>Hover mouse over each to see how the cursor looks</p>

<p class="alias">cursor: alias</p>
<p class="all-scroll">cursor: all-scroll</p>
<p class="auto">cursor: auto</p>
<p class="cell">cursor: cell</p>
<p class="context-menu">cursor: context-menu</p>
<p class="col-resize">cursor: col-resize</p>
<p class="copy">cursor: copy</p>
<p class="crosshair">cursor: crosshair</p>
<p class="default">cursor: default</p>
<p class="e-resize">cursor: e-resize</p>
<p class="ew-resize">cursor: ew-resize</p>
<p class="grab">cursor: grab</p>
<p class="grabbing">cursor: grabbing</p>
<p class="help">cursor: help</p>
<p class="move">cursor: move</p>
<p class="n-resize">cursor: n-resize</p>
<p class="ne-resize">cursor: ne-resize</p>
<p class="nesw-resize">cursor: nesw-resize</p>
<p class="ns-resize">cursor: ns-resize</p>
<p class="nw-resize">cursor: nw-resize</p>
<p class="nwse-resize">cursor: nwse-resize</p>
<p class="no-drop">cursor: no-drop</p>
<p class="none">cursor: none</p>
<p class="not-allowed">cursor: not-allowed</p>
<p class="pointer">cursor: pointer</p>
<p class="progress">cursor: progress</p>
<p class="row-resize">cursor: row-resize</p>
<p class="s-resize">cursor: s-resize</p>
<p class="se-resize">cursor: se-resize</p>
<p class="sw-resize">cursor: sw-resize</p>
<p class="text">cursor: text</p>
<p class="url">cursor: url</p>
<p class="w-resize">cursor: w-resize</p>
<p class="wait">cursor: wait</p>
<p class="zoom-in">cursor: zoom-in</p>
<p class="zoom-out">cursor: zoom-out</p>

Source: CSS cursor Property @ W3Schools

Syfer
  • 4,262
  • 3
  • 20
  • 37
Winfield Trail
  • 5,535
  • 2
  • 27
  • 43
7

I may be late, but you can try the following code, which worked for me for Drag and Drop.

.dndclass{
    cursor: url('../images/grab1.png'), auto; 

}

.dndclass:active {
    cursor: url('../images/grabbing1.png'), auto;
}

You can use the images below in the URL above. Make sure it is a PNG transparent image. If not, download one from google.

enter image description here enter image description here

Angel Politis
  • 10,955
  • 14
  • 48
  • 66
Jeeva
  • 632
  • 1
  • 12
  • 21
6

You can create your own cursors and set them as the cursor using cursor: url('path-to-your-cursor');, or find Firefox's and copy them (bonus: a nice consistent look in every browser).

j08691
  • 204,283
  • 31
  • 260
  • 272
Ry-
  • 218,210
  • 55
  • 464
  • 476
3

The closed hand cursor is not 16x16. If you would need them in the same dimensions, here you have both of them in 16x16 px

opened hand closed hand

Or if you need original cursors:

https://www.google.com/intl/en_ALL/mapfiles/openhand.cur https://www.google.com/intl/en_ALL/mapfiles/closedhand.cur

Zenon
  • 121
  • 7