Content types
Every content block in a column carries the Content envelope — id, type, and values. The type discriminates which shape values takes. This page is the per-type reference.
Content blocks render in four display modes — email, web, document, popup. Each mode exposes a subset of values fields (e.g. email-only border-collapse handling, web-only hover states). The embedded editor surfaces only the options that apply to the active mode. /v3/templates/validate applies the rules of one mode at a time — email unless you pass displayMode — so pass the mode your design was saved from.
Built-in types
There are 15 built-in content types. Modes lists the display modes where the type is available — "all" means email, web, popup, and document.
type | Modes | What it is |
|---|---|---|
button | all | A call-to-action button — label, link, color, border, padding, alignment. |
carousel | email, web, popup | An image slideshow. Interactive on web/popup and in AMP email. |
divider | all | A horizontal rule with color, thickness, and width controls. |
form | web, popup | A submittable form — configurable fields, layout, labels, and a submit button. |
heading | all | An h1–h4 heading. values.headingType controls the level. |
html | email, web, popup | A raw-HTML escape hatch. Use sparingly — the editor renders the string verbatim, no sanitization. |
image | all | An image with optional link, alt text, alignment, and per-device sizing. |
menu | email, web, popup | A navigation menu — a list of labeled links with a shared style. |
page_break | document | Forces a page break at this point when the document is exported. |
paragraph | all | A rich-text paragraph stored as Lexical editor state in values.textJson. The editor inserts these for new text content. |
social | all | A row of social-network icons with per-network URLs and a shared style. |
table | all | A data table with header, body, and footer bands and per-cell styling. |
text | all | The legacy rich-text block (TinyMCE era): values.text holds inline HTML. Kept for backward compatibility with existing templates — the editor now inserts paragraph (Lexical) instead. |
timer | email, web, popup | A countdown to a target timestamp. Renders a server-side image so it works in email clients without JS. |
video | email, web, popup | A YouTube/Vimeo video. Web and popup embed a player; email renders a linked thumbnail with an overlaid play icon. |
Shared properties
Nearly every type's values carries this common envelope of layout and behavior fields — the exact subset varies by type and display mode. They are documented once here and omitted from the per-type tables below.
| Property | Type | Notes |
|---|---|---|
containerPadding | string | CSS-style padding shorthand around the block, e.g. "10px" or "10px 20px". |
anchor | string | Optional fragment id for in-page anchor links. |
hideDesktop | boolean | Hide on desktop breakpoint. |
hideMobile | boolean | Hide on mobile breakpoint. |
displayCondition | object | null | Merge-tag-based show/hide condition; null = always show. |
_meta | { htmlID: string, htmlClassNames: string } | Stable identifiers for CSS targeting. Editor-managed. |
selectable, draggable, duplicatable, deletable, hideable | boolean | Per-block editor permissions (all default true). Set to false to lock that interaction in the editor. |
locked | boolean | Locks the block against all editing (default false). |
For the canonical per-type schema, validate a payload against /v3/templates/validate — the response will tell you exactly which fields are required and which are extras.
button
A call-to-action button with a label, click action, and full typography and box styling.
| Property | Type | Modes | Description |
|---|---|---|---|
text | string | Legacy inline-HTML label, kept for backward compatibility with existing templates — new designs should set textJson. | |
textJson | string | JSON-stringified Lexical editor state for the label — the current format (the editor is Lexical-based). | |
href | { name, attrs, values } | Click action: { name, values: { href, target } } — name is the action type (web, email, phone, ...). | |
buttonColors | { color, backgroundColor, hoverColor, hoverBackgroundColor } | { color, backgroundColor, hoverColor, hoverBackgroundColor } — CSS colors. | |
size | { autoWidth, width } | { autoWidth, width } — set autoWidth: false to honor width (e.g. "50%"). | |
fontFamily | { defaultFont, type, label, value, url, weights } | { label, value } — value is the CSS font stack; Google fonts also carry url. | |
fontSize | string | number | e.g. "14px". | |
lineHeight | string | e.g. "120%". | |
textAlign | 'left' | 'center' | 'right' | 'justify' | Button alignment in the column — left, center, right. | |
padding | string | Inner padding, e.g. "10px 20px". | |
border | object | Per-side keys: borderTopWidth, borderTopStyle, borderTopColor (and Left/Right/Bottom). | |
borderRadius | string | e.g. "4px". | |
_styleGuide | string | null | ||
ai_banner | never | ||
fontWeight | number | { label, value } | ||
letterSpacing | number | string | ||
suggestions | never | ||
synced | { id, dirty, updatedAt } | null |
carousel
An image slideshow. Fully interactive on web and popup and in the AMP email variant.
| Property | Type | Modes | Description |
|---|---|---|---|
showPreviews | boolean | email, web, popup | Show thumbnail previews under the active slide. |
previewWidth | number | string | email, web, popup | Thumbnail width, e.g. "100px". |
autoplay | boolean | email, web, popup | Auto-advance slides (AMP email variant only). |
loop | boolean | email, web, popup | Wrap from the last slide back to the first (AMP email variant only). |
_styleGuide | string | null | email, web, popup | |
ai_banner | never | email, web, popup | |
synced | { id, dirty, updatedAt } | null | email, web, popup |
The slides themselves live outside values: the content object carries a sibling embedded field — { "images": { "type": "image", "values": [ ... ] } } — with one image-shaped values object per slide (src, altText, action).
divider
A horizontal rule.
| Property | Type | Modes | Description |
|---|---|---|---|
width | number | string | Line length as a percentage of the column, e.g. "100%". | |
border | { borderTopColor, borderTopStyle, borderTopWidth } | { borderTopWidth, borderTopStyle, borderTopColor } — style is solid, dotted, dashed. | |
textAlign | 'left' | 'center' | 'right' | 'justify' | Where the line sits when narrower than the column — left, center, right. | |
_styleGuide | string | null | ||
ai_banner | never | ||
synced | { id, dirty, updatedAt } | null |
form
A submittable form with configurable fields and a submit button. web and popup modes only.
| Property | Type | Modes | Description |
|---|---|---|---|
action | { method, target, url } | web, popup | Submit endpoint: { url, method, target } — method is GET or POST, target is _self or _blank. |
fields | array<object> | web, popup | One object per field: { name, type, label, placeholder_text, show_label, required, options? } — options is a string array for choices. |
fieldWidth | string | web, popup | Width of each field, e.g. "100%". |
fieldDistance | string | web, popup | Vertical space between fields, e.g. "10px". |
formWidth | { autoWidth, width } | web, popup | { autoWidth, width }. |
formAlign | 'left' | 'center' | 'right' | 'justify' | web, popup | left, center, right. |
buttonText | number | string | web, popup | Submit button label. |
buttonColors | { color, backgroundColor, hoverColor, hoverBackgroundColor } | web, popup | { color, backgroundColor, hoverColor, hoverBackgroundColor }. |
buttonAlign | 'left' | 'center' | 'right' | 'justify' | web, popup | Submit button alignment. |
labelColor | string | web, popup | Field label color — see also labelFontFamily, labelFontSize, labelAlign. |
_styleGuide | string | null | web, popup | |
ai_banner | never | web, popup | |
buttonBorder | object | web, popup | |
buttonBorderRadius | string | web, popup | |
buttonFontFamily | { defaultFont, type, label, value, url, weights } | web, popup | |
buttonFontSize | string | number | web, popup | |
buttonMargin | string | web, popup | |
buttonPadding | string | web, popup | |
buttonWidth | { autoWidth, width } | web, popup | |
fieldBackgroundColor | string | web, popup | |
fieldBorder | object | web, popup | |
fieldBorderRadius | string | web, popup | |
fieldColor | string | web, popup | |
fieldFontFamily | { defaultFont, type, label, value, url, weights } | web, popup | |
fieldFontSize | string | number | web, popup | |
fieldPadding | string | web, popup | |
labelAlign | 'left' | 'center' | 'right' | 'justify' | web, popup | |
labelFontFamily | { defaultFont, type, label, value, url, weights } | web, popup | |
labelFontSize | string | number | web, popup | |
labelPadding | string | web, popup | |
placeholderAlign | 'left' | 'center' | 'right' | 'justify' | web, popup | |
synced | { id, dirty, updatedAt } | null | web, popup |
heading
A heading. headingType controls the rendered level.
| Property | Type | Modes | Description |
|---|---|---|---|
text | string | Legacy inline-HTML heading text, kept for backward compatibility with existing templates — new designs should set textJson. | |
textJson | string | JSON-stringified Lexical editor state for the heading — the current format (the editor is Lexical-based). | |
headingType | 'h1' | 'h2' | 'h3' | 'h4' | h1, h2, h3, or h4. | |
fontSize | string | number | e.g. "22px". | |
fontFamily | { defaultFont, type, label, value, url, weights } | { label, value } — value is the CSS font stack. | |
fontWeight | number | { label, value } | 100–900. | |
color | string | Text color. | |
textAlign | 'left' | 'center' | 'right' | 'justify' | left, center, right, justify. | |
lineHeight | string | e.g. "140%". | |
linkStyle | object | { inherit, linkColor, linkHoverColor, linkUnderline, linkHoverUnderline } — inherit: true uses the body's link styling. | |
_styleGuide | string | null | ||
ai_banner | never | ||
letterSpacing | number | string | ||
suggestions | never | ||
synced | { id, dirty, updatedAt } | null |
html
A raw-HTML escape hatch.
| Property | Type | Modes | Description |
|---|---|---|---|
html | string | email, web, popup | Raw HTML rendered verbatim — no sanitization. |
_styleGuide | string | null | email, web, popup | |
ai_banner | never | email, web, popup | |
synced | { id, dirty, updatedAt } | null | email, web, popup |
image
An image with optional link and alt text.
| Property | Type | Modes | Description |
|---|---|---|---|
src | object | { url, width?, height?, autoWidth?, maxWidth? } — width/height are intrinsic pixel numbers; maxWidth is a percentage string. | |
altText | number | string | Alternate text for accessibility and blocked-image fallback. | |
textAlign | 'left' | 'center' | 'right' | 'justify' | Alignment in the column — left, center, right. | |
action | { name, attrs, values } | Optional click-through link: { name: "web", values: { href, target } }. | |
_styleGuide | string | null | ||
ai_banner | never | ||
suggestions | never | ||
synced | { id, dirty, updatedAt } | null |
menu
A navigation menu — a list of labeled links with a shared style.
| Property | Type | Modes | Description |
|---|---|---|---|
menu | { items } | email, web, popup | { items: [...] } — each item is { key, text, link }; key is a unique id, link is { name, values: { href, target } }. |
layout | 'horizontal' | 'vertical' | email, web, popup | horizontal or vertical. |
align | 'left' | 'center' | 'right' | 'justify' | email, web, popup | left, center, right. |
separator | string | email, web, popup | Text rendered between items in horizontal layout. |
textColor | string | email, web, popup | Item text color. |
linkColor | string | email, web, popup | Link color. |
fontFamily | { defaultFont, type, label, value, url, weights } | email, web, popup | { label, value }. |
fontSize | string | number | email, web, popup | e.g. "14px". |
padding | string | email, web, popup | Per-item padding, e.g. "5px 15px". |
_styleGuide | string | null | email, web, popup | |
ai_banner | never | email, web, popup | |
fontWeight | number | { label, value } | email, web, popup | |
letterSpacing | number | string | email, web, popup | |
synced | { id, dirty, updatedAt } | null | email, web, popup |
page_break
Forces a page break at this point when the document is exported. document mode only.
| Property | Type | Modes | Description |
|---|---|---|---|
color | string | document | Color of the page-break rule. |
_styleGuide | string | null | document | |
ai_banner | never | document | |
synced | { id, dirty, updatedAt } | null | document |
paragraph
A rich-text paragraph stored as Lexical editor state — the block the editor inserts for all new text content.
| Property | Type | Modes | Description |
|---|---|---|---|
textJson | string | JSON-stringified Lexical editor state. Required. | |
fontSize | string | number | e.g. "14px". | |
fontFamily | { defaultFont, type, label, value, url, weights } | { label, value } — value is the CSS font stack. | |
fontWeight | number | { label, value } | 100–900. | |
color | string | Text color. | |
textAlign | 'left' | 'center' | 'right' | 'justify' | left, center, right, justify. | |
lineHeight | string | e.g. "140%". | |
linkStyle | object | { inherit, linkColor, linkHoverColor, linkUnderline, linkHoverUnderline }. | |
_styleGuide | string | null | ||
ai_banner | never | ||
letterSpacing | number | string | ||
synced | { id, dirty, updatedAt } | null |
social
A row of social-network icons.
| Property | Type | Modes | Description |
|---|---|---|---|
icons | { iconType, icons, editor } | { iconType, icons: [{ name, url }] } — name is the network (e.g. "Facebook"), url the profile link. | |
align | 'left' | 'center' | 'right' | 'justify' | left, center, right. | |
iconSize | number | string | Icon size in pixels (15–72). | |
spacing | number | string | Space between icons in pixels. | |
_styleGuide | string | null | ||
ai_banner | never | ||
synced | { id, dirty, updatedAt } | null |
iconType picks the icon style: circle, circle-black, circle-white, rounded, rounded-black, squared, squared-black.
table
A data table with optional header and footer bands, striped rows, and per-cell styling.
| Property | Type | Modes | Description |
|---|---|---|---|
table | { headers, rows, footers } | The cell data: { headers, rows, footers }, each an array of { cells, height } rows — cell shape below. | |
columns | number | string | Column count (1–8); must match the number of cells per row. | |
rows | number | string | Body row count; must match table.rows.length. | |
border | object | Per-side table border (borderTopWidth, borderTopStyle, borderTopColor, ...). | |
enableHeader | boolean | Render the table.headers band. | |
enableFooter | boolean | Render the table.footers band. | |
stripedRows | boolean | Alternate body-row backgrounds. | |
stripedRowsBackgroundColor | string | Stripe color. | |
linkStyle | object | Link styling inside cells. | |
_styleGuide | string | null | ||
ai_banner | never | ||
cellBackgroundColor | { property, selectedCellId } | ||
cellColor | { property, selectedCellId } | ||
cellPadding | { property, selectedCellId } | ||
cellTextAlign | { property, selectedCellId } | ||
cellVerticalAlign | { property, selectedCellId } | ||
contentBackgroundColor | string | ||
contentColor | string | ||
contentFontFamily | { defaultFont, type, label, value, url, weights } | ||
contentFontSize | string | number | ||
contentFontWeight | number | { label, value } | ||
contentLetterSpacing | number | string | ||
contentLineHeight | string | ||
contentPadding | string | ||
contentTextAlign | 'left' | 'center' | 'right' | 'justify' | ||
contentVerticalAlign | 'top' | 'middle' | 'bottom' | ||
footerBackgroundColor | string | ||
footerColor | string | ||
footerFontFamily | { defaultFont, type, label, value, url, weights } | ||
footerFontSize | string | number | ||
footerFontWeight | number | { label, value } | ||
footerPadding | string | ||
footerTextAlign | 'left' | 'center' | 'right' | 'justify' | ||
footerVerticalAlign | 'top' | 'middle' | 'bottom' | ||
headerBackgroundColor | string | ||
headerColor | string | ||
headerFontFamily | { defaultFont, type, label, value, url, weights } | ||
headerFontSize | string | number | ||
headerFontWeight | number | { label, value } | ||
headerPadding | string | ||
headerTextAlign | 'left' | 'center' | 'right' | 'justify' | ||
headerVerticalAlign | 'top' | 'middle' | 'bottom' |
Each cell in table is { text?, textJson?, width, backgroundColor?, color?, textAlign?, verticalAlign?, padding? } — width is a percentage number, row height is in pixels, and cells store their content in textJson (Lexical editor state, the current format) with text as the legacy HTML field kept for existing templates — the same convention as button.
Each band also has a styling family of prefixed properties — header*, content*, and footer* (e.g. headerBackgroundColor, contentFontSize, footerColor) — covering font family, size, weight, colors, alignment, and padding per band.
text
The legacy rich-text block from the TinyMCE era. values.text holds inline HTML; merge tags work via {{ tag }}. Kept for backward compatibility with existing templates — the editor now uses Lexical and inserts paragraph blocks for new text content.
| Property | Type | Modes | Description |
|---|---|---|---|
text | string | Inline HTML — <a>, <strong>, <em>, spans for color/size. Required on this legacy block. | |
fontSize | string | number | e.g. "14px". | |
fontFamily | { defaultFont, type, label, value, url, weights } | { label, value } — value is the CSS font stack. | |
color | string | Text color. | |
textAlign | 'left' | 'center' | 'right' | 'justify' | left, center, right, justify. | |
lineHeight | string | e.g. "140%". | |
linkStyle | object | { inherit, linkColor, linkHoverColor, linkUnderline, linkHoverUnderline }. | |
_styleGuide | string | null | ||
ai_banner | never | ||
fontWeight | number | { label, value } | ||
letterSpacing | number | string | ||
synced | { id, dirty, updatedAt } | null |
timer
A countdown to a target timestamp, rendered server-side as an animated image so it works in email clients without JS.
| Property | Type | Modes | Description |
|---|---|---|---|
countdown | object | email, web, popup | The timer definition — key sub-fields below. |
countdown.endTime | string | email, web, popup | Target end time as "YYYY-MM-DDTHH:mm:ss" (no zone suffix — interpreted in timezone). |
countdown.timezone | string | email, web, popup | IANA timezone, e.g. "America/Los_Angeles". |
countdown.showLabels | boolean | email, web, popup | Show the Days/Hours/Minutes/Seconds labels. |
countdown.digitColor, countdown.labelColor, countdown.backgroundColor | string | email, web, popup | Colors for digits, labels, and the image background. |
countdown.digitFontSize, countdown.labelFontSize | number | email, web, popup | Font sizes in pixels; font families via digitFontFamily / labelFontFamily. |
width | { autoWidth, width } | email, web, popup | { autoWidth, width } — rendered image width. |
textAlign | 'left' | 'center' | 'right' | 'justify' | email, web, popup | Alignment in the column. |
altText | number | string | email, web, popup | Alternate text for the rendered image. |
action | { name, attrs, values } | email, web, popup | Optional click-through link: { name: "web", values: { href, target } }. |
_styleGuide | string | null | email, web, popup | |
ai_banner | never | email, web, popup | |
synced | { id, dirty, updatedAt } | null | email, web, popup |
video
A YouTube or Vimeo video. Web and popup embed a real player; email renders a linked thumbnail with an overlaid play icon (email clients can't run embedded players).
| Property | Type | Modes | Description |
|---|---|---|---|
video | object | email, web, popup | { url, type, videoId?, thumbnail?, playIconColor?, playIconSize? } — type is youtube or vimeo. |
href | { name, attrs, values } | email, web, popup | Click-through action for the email thumbnail: { name, values: { href, target } }. |
_styleGuide | string | null | email, web, popup | |
ai_banner | never | email, web, popup | |
synced | { id, dirty, updatedAt } | null | email, web, popup |
Custom tools
Embedders can register their own content types via unlayer.registerTool(...). Custom blocks carry an extra slug discriminator:
{
"type": "custom",
"slug": "my_pricing_block",
"values": {
/* shape defined by the embedder */
}
}
The values shape is whatever your tool definition declares — by default Unlayer validates the envelope and treats values as opaque. To go deeper, pass your tool declarations in the customTools field of /v3/templates/validate and each declared option is checked with the exact value schema a built-in tool would have. See Custom Tools for the registration API.
Related
- Design object — the root that contains everything.
- Block object — the rows / columns that hold these content items.
- Custom Tools — register your own content types.
- Validate — verify a design against the canonical schema.