---
title: "Image Node Pro"
description: "Add resizable images to your Tiptap editor with editable captions, keyboard navigation, alignment controls, and a floating toolbar."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/ui-components/node-components/image-node-pro"
---

# Image Node Pro

Add resizable images to your Tiptap editor with editable captions, keyboard navigation, alignment controls, and a floating toolbar.

An enhanced image node component for Tiptap editors. Features drag-to-resize, editable captions, keyboard-safe navigation, floating toolbar controls, image alignment options, download functionality, responsive styling, and accessible interaction patterns.

> **Interactive demo:** [image node pro](https://template.tiptap.dev/preview/tiptap-node/image-node-pro)

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add image-node-pro floating-element toolbar
```

> **Where is the source code?:**
>
> The preview above is a live demo. The command installs Image Node Pro and the `FloatingElement`
> and `Toolbar` wrappers used by the example below. Tiptap UI Components are delivered as editable
> source files copied into your project (under `@/components/…`), not as an npm package. That is why
> the imports resolve to files in your own codebase rather than a module in `node_modules`.

### Update an existing installation

UI Components are copied into your project, so existing installations do not update automatically.
To receive the complete image, floating element, and toolbar fixes, reinstall them with overwrite
enabled:

```bash
npx @tiptap/cli@latest add image-node-pro floating-element toolbar -o
```

> **Review local customizations first:**
>
> The `-o` flag overwrites installed component files. Commit or review local customizations before
> running the update.

## Usage

```tsx
import { EditorContent, EditorContext, useEditor } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'
import { Image } from '@/components/tiptap-node/image-node/image-node-extension'
import { ImageNodeFloating } from '@/components/tiptap-node/image-node/image-node-floating'
import { Toolbar, ToolbarGroup } from '@/components/tiptap-ui-primitive/toolbar'
import { FloatingElement } from '@/components/tiptap-ui-utils/floating-element'

import '@/components/tiptap-node/image-node/image-node.scss'

export default function ImageEditor() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit, Image],
    content: '<img src="/images/example.png" alt="Image" data-align="center" />',
  })

  return (
    <EditorContext.Provider value={{ editor }}>
      <EditorContent editor={editor} />

      <FloatingElement>
        <Toolbar variant="floating">
          <ToolbarGroup>
            <ImageNodeFloating />
          </ToolbarGroup>
        </Toolbar>
      </FloatingElement>
    </EditorContext.Provider>
  )
}
```

`EditorContext.Provider` is required here because the actions rendered by `ImageNodeFloating` read the
editor from context. `FloatingElement` positions the controls relative to the selected image, while
`Toolbar` supplies the accessible toolbar interaction model.

## Features

- Drag-to-resize: hover an image and drag the handle on either side to set its width
- Editable image captions
- Floating toolbar with alignment controls
- Image download functionality
- Delete node button
- Alignment options (left, center, right)
- Configured HTML attributes are preserved when serializing bare and captioned images
- Enhanced accessibility
- Responsive image sizing
- Selection highlighting
- Stable image selection after content is inserted before or after the node
- Keyboard navigation around captionless images and into or out of visible captions
- Predictable undo boundaries for image deletion and resizing
- Read-only-safe captions and resize controls

### Selection and caption behavior

Image Node Pro tracks its document position as surrounding content changes, so clicking the image
continues to create a node selection after blocks are inserted or edited before it. Captionless
images behave like atomic blocks during keyboard navigation: the caret skips their hidden caption
content instead of entering an invisible text position. Visible captions remain editable and
navigable.

Empty captions close when focus leaves the image or when you press `Escape`. Populated captions
remain visible, including in read-only editors. Image deletion and resize commits use separate undo
boundaries, so the first undo restores the deleted image or previous size without also reverting the
latest caption edit.

### Keyboard behavior

| Key                                               | Behavior                                                                                                                              |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `ArrowUp`, `ArrowDown`, `ArrowLeft`, `ArrowRight` | Move around captionless images without entering hidden caption content, and enter or leave visible captions at their boundaries.      |
| `Enter`                                           | Leave the selected image or caption and move into an existing or new paragraph after the image.                                       |
| `Shift+Enter`, `Mod+Enter`                        | Insert a hard break while editing a caption when the editor schema supports hard breaks.                                              |
| `Backspace`, `Delete`                             | Edit text normally inside a caption. At an image boundary, select the image first; pressing the key again removes the selected image. |
| `Escape`                                          | Return to image node selection and close the caption when it is empty.                                                                |
| `Mod+A`                                           | In a non-empty caption, select the caption content first, then progress to the whole document.                                        |

The floating image toolbar uses horizontal roving focus. Press `Tab` to enter it, use `ArrowLeft`,
`ArrowRight`, `Home`, and `End` to move between controls, and press `Enter` (or native `Space` on a
button) to activate the focused control. `Tab` and `Shift+Tab` leave the toolbar instead of trapping
focus.

### HTML input and output

Captionless images serialize as `<img>` elements. Images with a visible or populated caption
serialize as a `<figure>` containing one `<img>` and one `<figcaption>`. Configured `HTMLAttributes`
are applied to the serialized `<img>` in both forms.

When parsing HTML, positive `width` and `height` values are normalized to numbers; invalid, zero, or
negative dimensions are ignored. The `allowBase64` option is applied consistently to bare images and
images inside figures. A figure is treated as a single captioned image only when it contains exactly
one valid direct-child `<img>`. Figures containing multiple images are not collapsed into one node;
eligible images remain separate.

## Extensions

### `Image` (Enhanced)

Extends the Tiptap Image extension with inline caption content, figure parsing and serialization,
alignment attributes, isolating keyboard behavior, and a tracked resizable React node view.

#### Usage

```tsx
import { Image } from '@/components/tiptap-node/image-node/image-node-extension'

const editor = useEditor({
  extensions: [StarterKit, Image],
})
```

## Floating Toolbar Components

`ImageNodeFloating` renders the image action group. When it is mounted inside `FloatingElement` and
`Toolbar`, the controls appear whenever an image is selected.

### `<ImageNodeFloating />`

Combines the alignment, caption, download, replace, and delete actions for the selected image.

### `<DeleteNodeButton />`

Remove the selected image node from the editor.

### `<ImageDownloadButton />`

Download the image to the user's device.

### `<ImageAlignButton />`

Control image alignment with options for left, center, and right alignment.

### `<ImageCaptionButton />`

Show or hide the editable caption for the selected image.

### `<ImageUploadButton />`

Replaces the selected image when the editor schema includes the `imageUpload` extension. The Replace
action stays hidden when that extension is unavailable.

## How It Works

The image node system works through several integrated layers:

1. **Enhanced Display**: Extends the basic Tiptap Image extension with additional styling and responsive behavior
2. **Floating Toolbar**: Provides contextual controls that appear when an image is selected
3. **Resizing**: Drag handles on either side of a hovered image let you set its width interactively
4. **Alignment System**: Manages image positioning with left, center, and right alignment options
5. **Node Management**: Handles image deletion and download functionality through toolbar actions
6. **State Integration**: Seamlessly integrates with Tiptap's node system and command architecture

After you mount `FloatingElement`, `Toolbar`, and `ImageNodeFloating` as shown above, selecting an image
opens the floating toolbar with alignment, caption, download, optional replace, and delete controls.

## Requirements

### Dependencies

- `@tiptap/core` - Core types and HTML attribute utilities
- `@tiptap/extension-image` - Core image extension
- `@tiptap/pm` - ProseMirror model, selection, transaction, and history utilities
- `@tiptap/react` - React integration
- `sass` - SCSS compiler development dependency
- `sass-embedded` - Embedded Sass development dependency

### Referenced Components

The `image-node-pro` registry item installs these direct registry dependencies automatically:

- `image-node` (node component and styles)
- `use-tiptap-editor` (hook)
- `tiptap-utils` (lib)
- `delete-node-button` (component)
- `image-download-button` (component)
- `image-align-button` (component)
- `image-caption-button` (component)
- `image-upload-button` (component)
- `refresh-ccw-icon` (icon)
- `separator` (primitive)
- `styles` (shared styles)

The quick-start install command adds `floating-element` and `toolbar` separately because they compose
the contextual toolbar around Image Node Pro rather than being imported by the image node itself.
