CSS Cursor
In this page:
Standard Cursor Values
CSS defines many built-in cursor keywords beyond pointer and default, including text, move, grab, help, wait, crosshair, and directional resize cursors like ns-resize. Choosing the right cursor keyword is a small but meaningful signal to users about what an element does before they even click it.
Note: Use cursor: help on elements with a tooltip so users know hovering will reveal more information.
Warning: Overusing exotic cursor values like crosshair or wait outside their expected context can confuse users about what the interface is doing.
Example: Standard Cursor Values
<style>
.help { cursor: help; background: #eef; padding: 6px 12px; display: inline-block; }
.move { cursor: move; background: #efe; padding: 6px 12px; display: inline-block; }
.grab { cursor: grab; background: #fee; padding: 6px 12px; display: inline-block; }
</style>
<span class="help">Help</span>
<span class="move">Move</span>
<span class="grab">Grab</span>
Custom Cursor Images
cursor accepts one or more image URLs followed by a required fallback keyword, letting you use a branded custom cursor while still degrading gracefully. If none of the image URLs load successfully, the browser silently falls back to the required keyword at the end of the list.
Note: Keep custom cursor images small, roughly 32 by 32 pixels, so they render crisply and load quickly.
Warning: Always end a custom cursor declaration with a standard keyword like pointer, without a fallback the cursor silently disappears if the image fails.
Example: Custom Cursor Images
<style>
.box {
cursor: url('custom-cursor.png'), pointer;
background: lightblue;
padding: 20px;
}
</style>
<div class="box">Falls back to pointer if the image fails</div>
cursor: pointer on Buttons
pointer is the most common cursor value, showing a hand icon over anything clickable, and is especially important on non-native interactive elements like styled divs and spans acting as buttons.
Note: Native button and a elements already show pointer by default in most browsers, but adding it explicitly documents the intent clearly in your stylesheet.
Warning: Setting cursor: pointer does not make an element keyboard accessible or add a click handler, it only changes the visual hint.
Example: cursor: pointer on Buttons
<style>
.fake-button {
cursor: pointer;
background: royalblue;
color: white;
display: inline-block;
padding: 10px 20px;
}
</style>
<div class="fake-button">Styled div acting as a button</div>
cursor: not-allowed for Disabled Elements
not-allowed shows a circle with a line through it, clearly communicating that an element exists but cannot currently be interacted with, commonly paired with disabled form controls.
Note: Combine cursor: not-allowed with reduced opacity on disabled buttons so the disabled state is obvious both visually and through the cursor.
Warning: Native disabled buttons already show not-allowed automatically in most browsers, manually setting it on a non-disabled element can send a false signal.
Example: cursor: not-allowed for Disabled Elements
<style>
button:disabled {
cursor: not-allowed;
opacity: 0.5;
}
</style>
<button disabled>Can't click me</button>
Cursor on Interactive States and Overlays
You can change cursor dynamically with pseudo-classes like :hover, or apply it globally to full-page overlays such as loading screens or modal backdrops. A cursor change on hover is often the only visual cue that an otherwise plain-looking element is actually clickable.
Note: Set cursor: wait on a full-page loading overlay so users understand the interface is busy processing something.
Warning: A cursor set on a parent overlay is inherited by its children unless a child explicitly overrides cursor itself.
Example: Cursor on Interactive States and Overlays
<style>
.card {
background: lightblue;
padding: 10px;
margin-bottom: 8px;
}
.card:hover {
cursor: pointer;
}
.overlay {
background: #333;
color: white;
padding: 10px;
cursor: wait;
}
</style>
<div class="card">Hover to see the pointer cursor</div>
<div class="overlay">Full-page loading overlay</div>
- Leaving the default cursor on custom-styled clickable divs, visitors may not realize a styled div is interactive without a pointer cursor.
- Using cursor: pointer on elements that are not actually clickable, which misleads users into expecting an action.
- Forgetting a fallback keyword after a custom cursor image, if the image fails to load the browser has nothing to fall back to.
- cursor changes the mouse pointer shape to communicate what will happen when a user interacts with an element.
- Custom cursor images can be set with a URL followed by a fallback keyword like pointer or auto.
- cursor: pointer signals clickable elements, while cursor: not-allowed signals a disabled or blocked action.
The cursor property and its standard keyword values are supported by all modern and legacy browsers; custom image cursors are supported everywhere except very old browser versions.
Chapter Quiz — Complete all 25 topics to unlock
0/25 topics done
Complete these topics first:
- CSS Container Queries
- CSS Subgrid
- CSS Logical Properties
- CSS Logical Sizing
- CSS Writing Modes
- CSS Aspect Ratio
- CSS Object Fit
- CSS object-position
- CSS Masking
- CSS Math Functions
- CSS Motion Path
- CSS @supports
- CSS @property
- CSS At-Rules
- CSS Cursor
- CSS Will Change
- CSS User Interface
- CSS Print Styles
- CSS Pagination (Print)
- CSS Dark Mode
- CSS Accessibility
- CSS Performance
- CSS Preprocessors
- CSS Frameworks Overview
- CSS Interview Prep