Skillversitas

CSS Cursor

What is Cursor?

The cursor property determines the type of mouse cursor displayed when the user hovers the pointer over an element. The right cursor gives users a visual hint about what they can do — click, drag, select text, and so on.

Using the right cursor is part of User Experience (UX) Design that is often overlooked, but it greatly affects how users interact with a website.

Cursor Types

Basic Cursors

Value Description When to Use
default Default arrow cursor Non-interactive elements
pointer Hand with a pointing finger Links, buttons, clickable elements
text I-beam Text input areas, text selection
wait Hourglass / loading A process is running
help Question mark Elements with help/tooltip

Action Cursors

Value Description When to Use
move Four-direction arrow Elements that can be dragged
crosshair Plus sign Selection area, cropping
grab Open hand Drag handle, scrollable area
grabbing Grasping hand While a drag is in progress
zoom-in Magnifying glass + Click to zoom in
zoom-out Magnifying glass - Click to zoom out

Resize Cursors

Value Description
col-resize Horizontal arrow (change width)
row-resize Vertical arrow (change height)
e-resize / w-resize East/west arrow
n-resize / s-resize North/south arrow
ne-resize / sw-resize Northeast/southwest arrow
nw-resize / se-resize Northwest/southeast arrow

Other Cursors

Value Description
not-allowed Red cross — action not allowed
no-drop Cross — drop not allowed
none No cursor
alias Double arrow — create shortcut
copy Plus sign — copy element
progress Clock with arrow — loading but still interactive
cell Small plus sign — select cell

Custom Cursor

CSS allows using a custom image as a cursor:

cursor: url('custom-cursor.png'), auto;

Supported formats: PNG, SVG, GIF, and CUR. It is recommended to provide a fallback auto or default after the custom cursor.

cursor: url('cursor.png') 12 12, pointer;
/* The numbers after the URL are the hotspot (the cursor's reference point) */

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Cursor</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: Arial, sans-serif;
      background-color: #f5f5f5;
      padding: 20px;
      color: #333;
    }

    h1 {
      margin-bottom: 25px;
    }

    .section {
      background-color: white;
      border-radius: 8px;
      padding: 20px;
      margin-bottom: 25px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
    }

    h2 {
      margin-bottom: 15px;
      color: #2c3e50;
    }

    p {
      line-height: 1.6;
      color: #555;
      margin-bottom: 10px;
    }

    code {
      background-color: #f0f0f0;
      padding: 2px 6px;
      border-radius: 3px;
      font-size: 13px;
    }

    /* === Basic Cursor Grid === */
    .cursor-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      gap: 10px;
    }

    .cursor-box {
      padding: 15px;
      text-align: center;
      background-color: #f8f9fa;
      border: 2px solid #e9ecef;
      border-radius: 6px;
      font-size: 12px;
      font-weight: bold;
      color: #555;
      transition: all 0.2s;
    }

    .cursor-box:hover {
      background-color: #e9ecef;
      border-color: #dee2e6;
    }

    .cursor-default { cursor: default; }
    .cursor-pointer { cursor: pointer; }
    .cursor-text { cursor: text; }
    .cursor-wait { cursor: wait; }
    .cursor-help { cursor: help; }
    .cursor-move { cursor: move; }
    .cursor-crosshair { cursor: crosshair; }
    .cursor-grab { cursor: grab; }
    .cursor-grabbing { cursor: grabbing; }
    .cursor-zoom-in { cursor: zoom-in; }
    .cursor-zoom-out { cursor: zoom-out; }
    .cursor-not-allowed { cursor: not-allowed; }
    .cursor-col-resize { cursor: col-resize; }
    .cursor-row-resize { cursor: row-resize; }
    .cursor-alias { cursor: alias; }
    .cursor-copy { cursor: copy; }
    .cursor-none { cursor: none; }

    /* === Interactive Elements === */
    .interactive-demo {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
    }

    .demo-btn {
      padding: 12px 24px;
      border: 2px solid #3498db;
      background-color: white;
      color: #3498db;
      border-radius: 6px;
      font-size: 14px;
      font-weight: bold;
      cursor: pointer;
      transition: all 0.2s;
    }

    .demo-btn:hover {
      background-color: #3498db;
      color: white;
    }

    .demo-link {
      color: #3498db;
      text-decoration: underline;
      cursor: pointer;
      font-size: 14px;
      padding: 12px;
    }

    .demo-disabled {
      padding: 12px 24px;
      border: 2px solid #ddd;
      background-color: #f5f5f5;
      color: #bbb;
      border-radius: 6px;
      font-size: 14px;
      cursor: not-allowed;
    }

    .demo-draggable {
      width: 150px;
      height: 80px;
      background-color: #2ecc71;
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      font-size: 14px;
      border-radius: 8px;
      cursor: grab;
    }

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

    .demo-text-select {
      padding: 12px;
      background-color: #ecf0f1;
      border-radius: 6px;
      cursor: text;
      font-size: 14px;
      user-select: text;
    }

    /* === Resize Handle === */
    .resize-demo {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
    }

    .resize-box {
      background-color: #f8f9fa;
      border: 2px solid #ddd;
      border-radius: 6px;
      padding: 10px;
      font-size: 12px;
      text-align: center;
      color: #555;
    }

    .resize-col {
      width: 150px;
      height: 80px;
      cursor: col-resize;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
    }

    .resize-row {
      width: 150px;
      height: 80px;
      cursor: row-resize;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
    }

    .resize-ns {
      width: 150px;
      height: 80px;
      cursor: ns-resize;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
    }

    .resize-ew {
      width: 150px;
      height: 80px;
      cursor: ew-resize;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
    }

    .resize-nwse {
      width: 150px;
      height: 80px;
      cursor: nwse-resize;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
    }

    /* === Zoom Demo === */
    .zoom-demo {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
    }

    .zoom-box {
      width: 120px;
      height: 120px;
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      font-weight: bold;
      color: white;
      transition: transform 0.2s;
    }

    .zoom-in-box {
      background-color: #3498db;
      cursor: zoom-in;
    }

    .zoom-in-box:hover {
      transform: scale(1.05);
    }

    .zoom-out-box {
      background-color: #e74c3c;
      cursor: zoom-out;
    }

    .zoom-out-box:hover {
      transform: scale(0.95);
    }

    /* === Copy/Paste Demo === */
    .copy-demo {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
    }

    .copy-box {
      padding: 15px;
      border: 2px dashed #ddd;
      border-radius: 6px;
      font-size: 13px;
      color: #555;
      text-align: center;
      transition: all 0.2s;
    }

    .copy-element {
      cursor: copy;
      background-color: #f8f9fa;
    }

    .copy-element:hover {
      background-color: #e9ecef;
      border-color: #3498db;
    }

    .alias-element {
      cursor: alias;
      background-color: #fff8e1;
    }

    .alias-element:hover {
      background-color: #fff3cd;
      border-color: #f39c12;
    }

    /* === Help Tooltip === */
    .help-demo {
      display: flex;
      gap: 15px;
      align-items: center;
      flex-wrap: wrap;
    }

    .help-trigger {
      cursor: help;
      color: #3498db;
      font-weight: bold;
      font-size: 14px;
      padding: 8px 16px;
      background-color: #eaf4fe;
      border-radius: 6px;
      border: 1px dashed #3498db;
      position: relative;
    }

    .help-trigger:hover::after {
      content: 'This is a help tooltip — the cursor changes to help (?)';
      position: absolute;
      bottom: 100%;
      left: 50%;
      transform: translateX(-50%);
      background-color: #333;
      color: white;
      padding: 8px 12px;
      border-radius: 4px;
      font-size: 12px;
      white-space: nowrap;
      margin-bottom: 8px;
    }

    /* === No Cursor === */
    .no-cursor-box {
      width: 200px;
      height: 80px;
      background-color: #ecf0f1;
      border: 2px solid #ddd;
      border-radius: 6px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: none;
      font-size: 13px;
      color: #555;
    }

    .label {
      font-size: 11px;
      color: #888;
      text-align: center;
      margin-top: 5px;
    }

    /* === Practical: Interactive Card === */
    .card-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
      gap: 15px;
    }

    .interactive-card {
      background-color: white;
      border: 2px solid #eee;
      border-radius: 8px;
      padding: 20px;
      cursor: pointer;
      transition: all 0.2s;
    }

    .interactive-card:hover {
      border-color: #3498db;
      box-shadow: 0 4px 12px rgba(52, 152, 219, 0.15);
      transform: translateY(-2px);
    }

    .interactive-card:active {
      transform: translateY(0);
      cursor: grabbing;
    }

    .interactive-card h4 {
      margin-bottom: 8px;
      color: #2c3e50;
    }

    .interactive-card p {
      font-size: 13px;
      color: #666;
      line-height: 1.5;
    }
  </style>
</head>
<body>

  <h1>CSS Cursor</h1>

  <!-- Basic Cursors -->
  <div class="section">
    <h2>Cursor Types</h2>
    <p>Move your mouse over each box to see the cursor changes:</p>
    <div class="cursor-grid">
      <div class="cursor-box cursor-default">default<br>(Arrow cursor)</div>
      <div class="cursor-box cursor-pointer">pointer<br>(Pointing hand)</div>
      <div class="cursor-box cursor-text">text<br>(I-beam text)</div>
      <div class="cursor-box cursor-wait">wait<br>(Loading)</div>
      <div class="cursor-box cursor-help">help<br>(Help)</div>
      <div class="cursor-box cursor-move">move<br>(Four directions)</div>
      <div class="cursor-box cursor-crosshair">crosshair<br>(Plus)</div>
      <div class="cursor-box cursor-grab">grab<br>(Open hand)</div>
      <div class="cursor-box cursor-grabbing">grabbing<br>(Closed fist)</div>
      <div class="cursor-box cursor-zoom-in">zoom-in<br>(Zoom in)</div>
      <div class="cursor-box cursor-zoom-out">zoom-out<br>(Zoom out)</div>
      <div class="cursor-box cursor-not-allowed">not-allowed<br>(Not allowed)</div>
      <div class="cursor-box cursor-col-resize">col-resize<br>(Width)</div>
      <div class="cursor-box cursor-row-resize">row-resize<br>(Height)</div>
      <div class="cursor-box cursor-alias">alias<br>(Shortcut)</div>
      <div class="cursor-box cursor-copy">copy<br>(Copy)</div>
      <div class="cursor-box cursor-none">none<br>(Invisible)</div>
    </div>
  </div>

  <!-- Interactive Elements -->
  <div class="section">
    <h2>Cursor on Interactive Elements</h2>
    <p>The right cursor gives users a hint about the available actions:</p>
    <div class="interactive-demo">
      <button class="demo-btn">Click Button</button>
      <a class="demo-link">Interactive Link</a>
      <div class="demo-disabled">Disabled Button</div>
      <div class="demo-draggable">Drag Me</div>
      <div class="demo-text-select">Select this text</div>
    </div>
  </div>

  <!-- Resize Handles -->
  <div class="section">
    <h2>Resize Handles</h2>
    <p>Resize cursor for elements whose size can be changed:</p>
    <div class="resize-demo">
      <div>
        <div class="resize-box resize-col">col-resize</div>
        <div class="label">Horizontal</div>
      </div>
      <div>
        <div class="resize-box resize-row">row-resize</div>
        <div class="label">Vertikal</div>
      </div>
      <div>
        <div class="resize-box resize-ns">ns-resize</div>
        <div class="label">North-South</div>
      </div>
      <div>
        <div class="resize-box resize-ew">ew-resize</div>
        <div class="label">East-West</div>
      </div>
      <div>
        <div class="resize-box resize-nwse">nwse-resize</div>
        <div class="label">Diagonal</div>
      </div>
    </div>
  </div>

  <!-- Zoom -->
  <div class="section">
    <h2>Zoom In / Zoom Out</h2>
    <p>Zoom cursor for elements that can be enlarged or reduced:</p>
    <div class="zoom-demo">
      <div class="zoom-box zoom-in-box">Zoom In</div>
      <div class="zoom-box zoom-out-box">Zoom Out</div>
    </div>
  </div>

  <!-- Copy/Alias -->
  <div class="section">
    <h2>Copy & Alias</h2>
    <p>Special cursor for copy actions and shortcuts:</p>
    <div class="copy-demo">
      <div class="copy-box copy-element">
        Copy cursor — Click to copy
      </div>
      <div class="copy-box alias-element">
        Alias cursor — Click to open shortcut
      </div>
    </div>
  </div>

  <!-- Help -->
  <div class="section">
    <h2>Help Cursor</h2>
    <p>Help cursor for elements that have help:</p>
    <div class="help-demo">
      <span>Move your mouse here:</span>
      <span class="help-trigger">What is this? (?)</span>
    </div>
  </div>

  <!-- No Cursor -->
  <div class="section">
    <h2>Cursor: none</h2>
    <p>Hiding the cursor — useful for video players or presentations:</p>
    <div class="no-cursor-box">
      The cursor disappears when pointed here
    </div>
  </div>

  <!-- Practical Card -->
  <div class="section">
    <h2>Practical Example — Interactive Cards</h2>
    <p>Watch the cursor changes on the cards below:</p>
    <div class="card-grid">
      <div class="interactive-card">
        <h4>CSS Basics</h4>
        <p>Learn selectors, properties, and the box model.</p>
      </div>
      <div class="interactive-card">
        <h4>Flexbox</h4>
        <p>Master one-dimensional layout with flexbox.</p>
      </div>
      <div class="interactive-card">
        <h4>CSS Grid</h4>
        <p>Powerful and modern two-dimensional layout.</p>
      </div>
    </div>
  </div>

</body>
</html>

Code Explanation

  1. Cursor Types — A grid of 17 boxes with different cursor types. Users can hover their mouse over each box to feel the difference directly.

  2. Interactive Elements — Five examples of elements with the appropriate cursor:

  3. Button — cursor: pointer to indicate it is clickable
  4. Link — cursor: pointer is the default for links
  5. Disabled — cursor: not-allowed to indicate the action is unavailable
  6. Draggable — cursor: grab changes to cursor: grabbing when clicked
  7. Text Select — cursor: text for a selectable area

  8. Resize Handles — Five boxes with different resize directions:

  9. col-resize — For changing a column's width
  10. row-resize — For changing a row's height
  11. ns-resize — North-south (vertical)
  12. ew-resize — East-west (horizontal)
  13. nwse-resize — Diagonal

  14. Zoom — Two boxes that change size on hover: zoom-in scales up, zoom-out scales down.

  15. Copy & Alias — Special cursors for copy and shortcut actions.

  16. Help — An element with a tooltip that appears on hover, using the help cursor.

  17. None — An area where the cursor disappears completely.

  18. Interactive Cards — Cards that use cursor and transform to give visual feedback on hover and when active.


Everyday Use Cases

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    body {
      font-family: Arial, sans-serif;
      background-color: #f5f5f5;
    }

    /* === Image Viewer === */
    .viewer-header {
      background-color: #2c3e50;
      color: white;
      padding: 15px 20px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .viewer-header h1 {
      font-size: 18px;
    }

    .viewer-tools {
      display: flex;
      gap: 10px;
    }

    .tool-btn {
      width: 36px;
      height: 36px;
      border-radius: 6px;
      border: none;
      background-color: #34495e;
      color: white;
      font-size: 16px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .tool-btn:hover {
      background-color: #3498db;
    }

    .tool-btn.active {
      background-color: #3498db;
    }

    .viewer-canvas {
      background-color: #1a1a2e;
      height: 400px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #666;
      font-size: 16px;
      cursor: crosshair;
    }

    .viewer-footer {
      background-color: #2c3e50;
      color: white;
      padding: 12px 20px;
      font-size: 13px;
      display: flex;
      justify-content: space-between;
    }

    /* === Spreadsheet-like Table === */
    .spreadsheet {
      max-width: 800px;
      margin: 30px auto;
      background-color: white;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }

    .spreadsheet-header {
      padding: 15px 20px;
      background-color: #2c3e50;
      color: white;
      font-weight: bold;
      font-size: 16px;
    }

    .spreadsheet-grid {
      display: grid;
      grid-template-columns: 120px repeat(3, 1fr);
    }

    .cell {
      padding: 10px 14px;
      border: 1px solid #eee;
      font-size: 14px;
      color: #333;
      cursor: cell;
    }

    .cell:hover {
      background-color: #eaf4fe;
    }

    .cell-header {
      background-color: #f8f9fa;
      font-weight: bold;
      color: #2c3e50;
      cursor: default;
      border-bottom: 2px solid #ddd;
    }

    .cell-row-header {
      background-color: #f8f9fa;
      font-weight: bold;
      color: #555;
      cursor: row-resize;
    }

    .cell-editable {
      cursor: text;
    }

    .cell-editable:focus {
      outline: 2px solid #3498db;
      outline-offset: -2px;
      background-color: white;
    }
  </style>
</head>
<body>

  <!-- Image Viewer -->
  <div class="viewer-header">
    <h1>Image Viewer</h1>
    <div class="viewer-tools">
      <button class="tool-btn active" title="Pan">✋</button>
      <button class="tool-btn" title="Zoom In">🔍</button>
      <button class="tool-btn" title="Crop">⬒</button>
      <button class="tool-btn" title="Measure">📏</button>
    </div>
  </div>
  <div class="viewer-canvas">
    Canvas — The cursor changes according to the selected tool
  </div>
  <div class="viewer-footer">
    <span>Zoom: 100%</span>
    <span>Use scroll to zoom, drag to pan</span>
  </div>

  <!-- Spreadsheet Table -->
  <div class="spreadsheet">
    <div class="spreadsheet-header">Student Data</div>
    <div class="spreadsheet-grid">
      <div class="cell cell-header">Name</div>
      <div class="cell cell-header">CSS</div>
      <div class="cell cell-header">HTML</div>
      <div class="cell cell-header">JS</div>

      <div class="cell cell-row-header">John</div>
      <div class="cell cell-editable" tabindex="0">92</div>
      <div class="cell cell-editable" tabindex="0">88</div>
      <div class="cell cell-editable" tabindex="0">95</div>

      <div class="cell cell-row-header">Mike</div>
      <div class="cell cell-editable" tabindex="0">85</div>
      <div class="cell cell-editable" tabindex="0">90</div>
      <div class="cell cell-editable" tabindex="0">78</div>

      <div class="cell cell-row-header">Amy</div>
      <div class="cell cell-editable" tabindex="0">97</div>
      <div class="cell cell-editable" tabindex="0">93</div>
      <div class="cell cell-editable" tabindex="0">91</div>
    </div>
  </div>

</body>
</html>

In the example above:
- Image Viewer — A toolbar with buttons using cursor: pointer, and a canvas with cursor: crosshair for crop/selection mode
- Spreadsheet Table — Header cells use cursor: row-resize or cursor: default, editable cells use cursor: text, and regular cells use cursor: cell


Cursor Usage Tips

User Action Appropriate Cursor
Click to navigate pointer
Type text text
Wait for a process wait or progress
Drag & drop grab → grabbing
Resize col-resize, row-resize, etc.
Zoom zoom-in, zoom-out
Not available not-allowed
Help tooltip help

Conclusion

  • cursor: pointer — Most commonly used for links, buttons, and interactive elements
  • cursor: text — For text input areas and text selection
  • cursor: grab/grabbing — For drag and drop interactions
  • cursor: not-allowed — For disabled elements that cannot be interacted with
  • cursor: wait/progress — To indicate a process is running
  • cursor: none — Hides the cursor, useful for video players or presentations
  • Resize cursors (col-resize, row-resize) — For elements whose size can be changed
  • Custom cursors can use an image with cursor: url('image.png'), fallback
  • Using the right cursor improves UX and helps users understand the available interactions