image#
A static image, sized into a box with a choice of fit modes and optional color filters. Inherits common fields.
interface ImageElement extends BaseElement { type: "tok-str">'image'; source: string; fit?: "tok-str">'cover' | "tok-str">'contain' | "tok-str">'fill' | "tok-str">'none'; border_radius?: number; crop_x?: number; crop_y?: number; crop_width?: number; crop_height?: number; }
Color filters (brightness, contrast, saturation, blur_radius, hue_rotate) are common base fields shared by every element — they are documented under Filters below for convenience, not because they are image-specific.
Required#
| Field | Type | Default | Description |
|---|---|---|---|
source | string (URL) | required | HTTP(S) URL of the image. PNG, JPEG, WebP, and animated GIF (first frame only) are supported. Local file paths fail in the renderer today; see renderer docs. |
Layout#
| Field | Type | Default | Description |
|---|---|---|---|
fit | 'cover' | 'contain' | 'fill' | 'none' | 'cover' | How the image fills the element's box. Same semantics as CSS object-fit. |
border_radius | number | 0 | Corner radius in px applied to the element's box. |
cover— fill the box, crop overflow.contain— fit the whole image inside the box, letterbox if needed.fill— stretch to the box's aspect ratio.none— render at the image's natural pixel size, centered in the box and cropped to it.
Crop#
A normalized sub-rectangle of the source image, applied before fit. The element's box is unchanged — crop just chooses which part of the source fills it. Omit the fields (or leave the identity 0,0,1,1) for no crop. In the editor, the Crop widget in the Media section gives you both the numeric fields and a drag-to-resize frame over the image.
| Field | Type | Default | Description |
|---|---|---|---|
crop_x | number (0–1) | 0 | Left edge of the kept region, as a fraction of source width. |
crop_y | number (0–1) | 0 | Top edge, as a fraction of source height. |
crop_width | number (0–1) | 1 | Width of the kept region, as a fraction of source width. |
crop_height | number (0–1) | 1 | Height of the kept region, as a fraction of source height. |
Each component is keyframeable — animate the origin to pan and the size to zoom for a Ken Burns move that never touches the element's layout.
Filters#
These are common base fields available on every element; they are listed here because color adjustment is a frequent need on images. brightness, contrast, and saturation are multipliers with a neutral default of 1: 0 removes the channel, 1 leaves it unchanged, 2 doubles it. They are not a 0–200 percent scale. blur_radius is a Gaussian sigma in pixels and hue_rotate is in degrees.
| Field | Type | Default | Description |
|---|---|---|---|
brightness | number | 1 | Luminance multiplier. 0 = black; 1 = unchanged; 2 = double brightness. |
contrast | number | 1 | Contrast multiplier around mid-grey. 0 = solid mid-grey; 1 = unchanged; 2 = high-contrast. |
saturation | number | 1 | Saturation multiplier. 0 = grayscale; 1 = unchanged; 2 = oversaturated. |
blur_radius | number | 0 | Gaussian blur sigma in px (0 = none). |
hue_rotate | number | 0 | Hue rotation in degrees. |
Examples#
Full-bleed background with darkening#
{ "type": "image", "source": "https://images.unsplash.com/photo-...", "x": 0, "y": 0, "width": 1920, "height": 1080, "fit": "cover", "brightness": 0.6 }
The anchor defaults to top-left, so x: 0, y: 0 with the full canvas width/height covers the frame. (Setting x: 960, y: 540 would offset the anchor to the canvas center and push the image off-screen.)
Subtle blur for a depth-of-field effect#
{ "type": "image", "source": "https://example.com/backdrop.jpg", "fit": "cover", "blur_radius": 8 }
Grayscale logo#
{ "type": "image", "source": "https://example.com/logo.png", "fit": "contain", "saturation": 0 }
Crop to the center half of the source#
{ "type": "image", "source": "https://example.com/photo.jpg", "fit": "cover", "crop_x": 0.25, "crop_y": 0.25, "crop_width": 0.5, "crop_height": 0.5 }
Notes#
- Aspect-ratio mismatch — when
fitiscover, the image is centered within the box and the overflow is cropped equally on both sides; the crop is always centered (it is not steered byx_anchor/y_anchor, which only position the element's box). To choose which part of the source is shown, use thecrop_*fields. - Animated GIFs render at frame 0 only; use a
videoelement for moving image content. - Asset caching — the runtime caches fetched images by URL within a render. The hosted render API also caches across renders for the same URL.