image.create#
Type: false | function
Default: false
Replaces the built-in image insert UI. When set, image.open calls your function instead of opening the default dropdown.
const app = Redactor('#entry', {
image: {
create(app) {
// open your own picker / modal
}
}
});
image.edit#
Type: false | function
Default: false
Replaces the built-in image edit UI. When set, image.edit calls your function with the current image block.
const app = Redactor('#entry', {
image: {
edit(app, block) {
}
}
});
image.upload#
Type: false | string | 'base64' | function
Default: false
Enables file upload for images.
Modes
- URL string —
POSTto your endpoint withFormData. 'base64'— no server upload; images are converted client-side to data URLs.- Custom function — full control over the upload.
Required for drag-and-drop and clipboard paste of image files.
When upload is off, pasted HTML with images is still inserted (existing src values are kept).
Endpoint upload
const app = Redactor('#entry', {
image: {
upload: '/upload/',
}
});
The endpoint should return JSON.
Success — single image
{
"url": "/uploads/photo.jpg"
}
url or src is required (public image URL). Optional per-image fields: id, alt, caption, width, height, srcset, link (href when the image is wrapped in <a>).
Success — multiple images
Object with one entry per file (keys are arbitrary):
{
"file-0": { "url": "/uploads/a.jpg", "id": "abc" },
"file-1": { "url": "/uploads/b.jpg", "id": "def" }
}
Or an array:
[
{ "url": "/uploads/a.jpg" },
{ "url": "/uploads/b.jpg" }
]
Each item must be an object with url or src.
Error
Any object with a truthy error property is treated as failure (upload:error, image.error callback):
{
"error": true,
"message": "File type not allowed"
}
Custom upload function
const app = Redactor('#entry', {
image: {
upload(uploader, { data, files, e }) {
// data — FormData (already contains files under image.name)
// files — FileList from input / drop / paste
fetch('/api/upload', { method: 'POST', body: data })
.then((res) => res.json())
.then((json) => uploader.complete(json, e))
.catch((err) => uploader.complete({ error: true, message: String(err) }, e));
}
}
});
Base64 mode
const app = Redactor('#entry', {
image: {
upload: 'base64',
convertFormat: 'image/webp',
convertQuality: 0.8
}
});
No HTTP request; complete receives an array like [{ name: 'photo.webp', url: 'data:image/webp;base64,…', base64: true }].
image.url#
Type: boolean
Default: true
Shows the By URL tab in the image dropdown and allows inserting an image by pasting a direct image URL.
When image.url is the only insert source enabled (upload and select are off), the dropdown opens as a simple URL form without tabs.
const app = Redactor('#entry', {
image: {
url: false,
upload: '/upload/'
}
});
image.select#
Type: false | string | object
Default: false
Enables the Select tab — a grid of thumbnails loaded from a server or from inline data.
- URL string — JSON endpoint; request method from
image.selectMethod - Object / array — preloaded list of images
const app = Redactor('#entry', {
image: {
select: '/api/images.json'
}
});
JSON format
The endpoint (or inline value) must be a JSON array or an object whose values are image entries. Each entry is an object:
| Field | Required | Description |
|---|---|---|
url |
yes* | Full-size image URL inserted into the document (<img src>) |
thumb |
yes* | Thumbnail URL shown in the select grid. If omitted, url is used |
id |
no | Stored on the image block |
alt |
no | alt attribute |
caption |
no | Figure caption; adding one converts a p/div wrapper to <figure> |
link |
no | Wraps the image in <a> |
width |
no | width attribute |
height |
no | height attribute |
Array (typical for a json file):
[
{
"thumb": "/uploads/photo-1-thumb.jpg",
"url": "/uploads/photo-1.jpg",
"id": "photo-1",
"alt": "Alternative text",
"caption": "My caption",
"link": "https://example.com"
},
{
"thumb": "/uploads/photo-2-thumb.jpg",
"url": "/uploads/photo-2.jpg",
"id": "photo-2",
"width": "300",
"height": "100"
}
]
Object (arbitrary keys):
{
"photo-1": { "thumb": "/uploads/a-thumb.jpg", "url": "/uploads/a.jpg" },
"photo-2": { "thumb": "/uploads/b-thumb.jpg", "url": "/uploads/b.jpg" }
}
Inline preload:
const app = Redactor('#entry', {
image: {
select: [
{ thumb: '/thumb.jpg', url: '/full.jpg', alt: 'Photo' }
]
}
});
image.selectMethod#
Type: string
Default: 'get'
HTTP method for the image.select endpoint ('get' or 'post').
const app = Redactor('#entry', {
image: {
select: '/api/images.json',
selectMethod: 'post'
}
});
image.name#
Type: string
Default: 'file'
Form field name for the uploaded file in multipart requests.
const app = Redactor('#entry', {
image: {
upload: '/upload/',
name: 'my-file'
}
});
image.data#
Type: false | object
Default: false
Extra fields merged into upload FormData (CSRF token, folder id, etc.).
const app = Redactor('#entry', {
image: {
upload: '/upload/',
data: { folder: 'content' }
}
});
image.drop#
Type: boolean
Default: true
Allows dragging image files into the editor. Requires image.upload to be enabled.
Set to false to ignore file drops.
const app = Redactor('#entry', {
image: {
drop: false
}
});
image.multiple#
Type: boolean
Default: true
Allows selecting and uploading more than one file at a time in the upload tab and drag-and-drop handler.
const app = Redactor('#entry', {
image: {
upload: '/upload/',
multiple: false
}
});
image.clipboard#
Type: boolean
Default: true
Handles pasted image files from the clipboard. Requires image.upload for file blobs.
When image.upload is a server URL, pasted data:image/... inside HTML is uploaded and replaced with returned URLs before insert. In base64 mode, data URLs are kept.
const app = Redactor('#entry', {
image: {
upload: '/upload/',
clipboard: false
}
});
image.types#
Type: string[]
Default: ['image/*']
Allowed MIME types for the file input accept attribute.
const app = Redactor('#entry', {
image: {
types: ['image/jpeg', 'image/png', 'image/webp']
}
});
image.tag#
Type: string
Default: 'figure'
Wrapper tag for new image blocks (upload, insert, bare <img> without a wrapper). Existing wrappers from content or paste (<p>, <div>, <figure>) are preserved.
When a caption is added in the image edit form, a p or div wrapper is converted to <figure> and all wrapper attributes are kept.
const app = Redactor('#entry', {
image: {
tag: 'div'
}
});
image.link#
Type: boolean
Default: true
Shows the Link and Open link in new tab fields in the image properties form.
When false, link UI is hidden.
const app = Redactor('#entry', {
image: {
link: false
}
});
image.width#
Type: boolean
Default: false
Controls the Width field in the image edit form.
const app = Redactor('#entry', {
image: {
upload: '/upload/',
width: true
}
});
image.height#
Type: boolean
Default: false
Controls the Height field in the image edit form.
const app = Redactor('#entry', {
image: {
upload: '/upload/',
height: true
}
});
image.convertFormat#
Type: string
Default: 'image/webp'
Target format for client-side image conversion (base64 upload mode and clipboard re-encoding).
const app = Redactor('#entry', {
image: {
upload: 'base64',
convertFormat: 'image/avif'
}
});
Use MIME types:
image/webp
image/jpeg
image/jpg
image/png
image/avif
image.convertQuality#
Type: number
Default: 0.8
Quality for lossy conversion (0–1), used with image.convertFormat.
const app = Redactor('#entry', {
image: {
upload: 'base64',
convertFormat: 'image/avif',
convertQuality: 1
}
});
outset#
Type: object | false
Default:
{
none: 'none',
left: 'outset-left',
both: 'outset-both',
right: 'outset-right'
}
Preset map for the Outset dropdown on image blocks. Keys are UI ids; values are CSS classes applied to the image wrapper.
Outset shifts the image outside the text column — left, right, or both sides — using layout classes from the editor stylesheet (outset-left, outset-right, outset-both). Width and offset use the --rx-outset CSS variable (default 26px).
Set to false to hide the Outset control in the image dropdown and context bar.
const app = Redactor('#entry', {
outset: false
});
Custom class names:
const app = Redactor('#entry', {
outset: {
none: 'none',
left: 'my-outset-left',
both: 'my-outset-both',
right: 'my-outset-right'
}
});
wrap#
Type: object | false
Default:
{
none: 'none',
left: 'float-left',
center: 'wrap-center',
right: 'float-right'
}
Preset map for the Wrap dropdown on image blocks. Keys are UI ids; values are CSS classes on the image wrapper.
Default classes from the editor stylesheet:
float-left/float-right— float the image beside text (max-width: var(--rx-float-width), margins via--rx-float-margin)wrap-center— centers the image and caption inside the blocknone— removes wrap alignment
Set to false to hide the Wrap control in the image dropdown and context bar.
const app = Redactor('#entry', {
wrap: false
});
Custom class names (add matching rules in your content CSS):
const app = Redactor('#entry', {
wrap: {
none: 'none',
left: 'img-float-left',
center: 'img-center',
right: 'img-float-right'
}
});
wrapWithStyle#
Type: false | boolean | object
Default: false
When enabled, Wrap applies inline styles instead of CSS classes from the wrap map.
true— use defaults:margin: 1em,marginBottom: 1em,maxWidth: 200px- object — same fields, any value can be overridden
For float left / float right, styles are set on the image block wrapper: float, maxWidth, marginBottom, and marginLeft or marginRight (side margin depends on float direction). Previous float styles and wrap classes are cleared first.
Center and none still use inline text-align / margin on the wrapper and image (no float).
const app = Redactor('#entry', {
wrapWithStyle: true
});
const app = Redactor('#entry', {
wrapWithStyle: {
margin: '1.5em',
marginBottom: '0.75em',
maxWidth: '240px'
}
});