Skip to main content
The gap cursor extension allows users to place the cursor between block nodes that normally don’t have selectable positions nearby, such as adjacent images or tables.

Installation

The gap cursor extension is included in the prosekit package.
import { defineGapCursor } from 'prosekit/extensions/gap-cursor'

Styling

You need to import the gap cursor styles to make the cursor visible:
import 'prosekit/extensions/gap-cursor/style.css'
Or add your own styles:
.ProseMirror-gapcursor {
  display: block;
  position: relative;
}

.ProseMirror-gapcursor:after {
  content: '';
  display: block;
  position: absolute;
  top: -2px;
  width: 20px;
  border-top: 1px solid black;
  animation: ProseMirror-gapcursor-blink 1.1s steps(2, start) infinite;
}

@keyframes ProseMirror-gapcursor-blink {
  to {
    visibility: hidden;
  }
}

Usage

import { createEditor } from 'prosekit/core'
import { defineGapCursor } from 'prosekit/extensions/gap-cursor'
import 'prosekit/extensions/gap-cursor/style.css'

const editor = createEditor({
  extension: defineGapCursor()
})

API reference

defineGapCursor()

Creates a gap cursor extension that captures clicks near and arrow-key-motion past places that don’t have a normally selectable position nearby. The cursor is drawn as an element with class ProseMirror-gapcursor.

Behavior

The gap cursor extension:
  • Captures clicks near positions without selectable content
  • Handles arrow keys to navigate through gap positions
  • Shows visual indicator at the gap cursor position
  • Works with block nodes like images, tables, and horizontal rules

Use cases

Adjacent images

Place cursor between two images without text

Before/after tables

Navigate to positions around tables

Around horizontal rules

Select positions near dividers

Block node boundaries

Navigate document structure

Examples

Basic setup with images

import { createEditor, union } from 'prosekit/core'
import { defineDoc, defineParagraph, defineText } from 'prosekit/extensions/doc'
import { defineImage } from 'prosekit/extensions/image'
import { defineGapCursor } from 'prosekit/extensions/gap-cursor'
import 'prosekit/extensions/gap-cursor/style.css'

const editor = createEditor({
  extension: union([
    defineDoc(),
    defineText(),
    defineParagraph(),
    defineImage(),
    defineGapCursor(),
  ])
})

With tables

import { createEditor, union } from 'prosekit/core'
import { defineDoc, defineParagraph, defineText } from 'prosekit/extensions/doc'
import { defineTable } from 'prosekit/extensions/table'
import { defineGapCursor } from 'prosekit/extensions/gap-cursor'
import 'prosekit/extensions/gap-cursor/style.css'
import 'prosekit/extensions/table/style.css'

const editor = createEditor({
  extension: union([
    defineDoc(),
    defineText(),
    defineParagraph(),
    defineTable(),
    defineGapCursor(),
  ])
})

Custom styling

/* Custom gap cursor color */
.ProseMirror-gapcursor:after {
  border-top: 2px solid #2563eb;
  width: 30px;
}

/* Larger cursor for better visibility */
.ProseMirror-gapcursor:after {
  top: -4px;
  border-top: 3px solid #2563eb;
}
  • Drop cursor - Visual indicator for drag-and-drop
  • Image - Image nodes that benefit from gap cursor
  • Table - Table nodes that benefit from gap cursor