Skip to content

Styled Text

The styled text field provides a rich text editor powered by Tiptap. It supports a wide range of settings for customizing the editor’s appearance, toolbar, and behavior.

Styled text is a structured editor, not an HTML pass-through. It parses the stored HTML into a document model of the elements it knows, and writes that model back out on save. Anything the model does not describe is normalized or dropped, and the save reports success either way — there is no warning. If you hand-author HTML into a styled text field and then open the record in the admin, expect the markup to come back changed.

What survives a load-and-save:

  • Headings, paragraphs, lists, blockquotes, code blocks, tables, images, figures, links, horizontal rules, hard breaks, and the inline formatting the toolbar offers
  • class, id, style and data-* attributes on those blocks, and on links and styled spans
  • Block wrappers such as section, aside, article, nav, header, footer, details, summary and any div with a class or id — kept with their element name and attributes, and shown in the editor as a labelled block whose contents you can edit
  • Inline elements such as kbd, abbr, cite, mark, time, small and button, with their attributes
  • Text inside a wrapper is normalized into paragraphs, so <summary>Q</summary> comes back as <summary><p>Q</p></summary>
  • Inline <svg>, kept verbatim
  • A list item may begin with any block — a heading, a figure or a wrapper — not only a paragraph

What changes:

  • Presentational tags are normalized: <b> becomes <strong>, <i> becomes <em>
  • A list item holding a single paragraph is unwrapped to bare text
  • A <figure> with an image gains data-type="figure-image" and an ste-figure class alongside your own classes; an image gains ste-img--* classes when it has a float or size
  • Style declarations are reserialized by the browser (color:red becomes color: red;)
  • A <p> containing only an image is split into an empty paragraph and a block image
  • Attributes on <strong>, <em>, <u>, <s>, <code> and the other toolbar marks are dropped

What is dropped: any element not listed above (iframe, object, canvas, form controls, script, style, custom elements), a div without a class or id (its contents are kept), and <a> attributes other than href, target, rel, class, style, title and data-*.

For content you author by hand and want stored byte-for-byte, use a code editor field with "mode": "html" and render it with the raw filter. Keep styled text for content editors will actually edit in the toolbar.

Control the editor’s height with these settings:

{
"height": 400
}
  • height - Fixed height in pixels. The editor will have exactly this height with vertical scrolling. When omitted, the editor uses a flexible height between heightMin and heightMax.
  • heightMin - Minimum editor height in pixels. Default: 200
  • heightMax - Maximum editor height in pixels. Default: 800

By default, the editor strips HTML formatting from pasted content and inserts plain text only. This prevents messy formatting when pasting from Word, Google Docs, or web pages.

{
"pasteAsPlainText": false
}
  • pasteAsPlainText - Strip HTML formatting from pasted content. Default: true

Set to false to allow pasting with rich formatting preserved.

The editor displays character and word counts in the footer. You can configure limits that highlight when exceeded.

{
"charCounterCount": true,
"charCounterMax": 5000,
"wordCounterCount": true,
"wordCounterMax": 1000
}
  • charCounterCount - Show character counter. Default: false
  • charCounterMax - Maximum character limit. Displays as “X / 5000 characters” and highlights in red when exceeded.
  • wordCounterCount - Show word counter. Default: true
  • wordCounterMax - Maximum word limit. Displays as “X / 1000 words” and highlights in red when exceeded.

Customize which buttons appear in the toolbar and their grouping:

{
"toolbarConfig": [
{ "name": "history", "buttons": ["undo", "redo"] },
{ "name": "text", "buttons": ["bold", "italic", "underline"] },
{ "name": "paragraph", "buttons": ["heading", "bulletList", "orderedList"] },
{ "name": "insert", "buttons": ["link", "image"] },
{ "name": "misc", "buttons": ["codeView", "fullscreen"], "align": "right" }
]
}

Each group has a name, a buttons array, and an optional align property ("right" to push the group to the right side of the toolbar).

Available toolbar buttons:

CategoryButtons
Historyundo, redo
Text Formattingbold, italic, underline, strike, superscript, subscript
Colors & StylingtextColor, textBgColor, inlineStyles, inlineClasses
Block Formattingheading, bulletList, orderedList, blockquote, indent, outdent, codeBlock, align
Insertlink, image, video, file, table, horizontalRule, hardBreak, htmlSnippets, anchor
BlockblockAttributes
Editor ControlsclearFormatting, codeView, fullscreen

Default toolbar:

[
{ "name": "text", "buttons": ["bold", "italic", "underline"] },
{ "name": "paragraph", "buttons": ["heading", "bulletList", "orderedList", "blockquote", "outdent", "indent"] },
{ "name": "insert", "buttons": ["link", "image", "horizontalRule"] },
{ "name": "misc", "buttons": ["clearFormatting", "codeView"], "align": "right" }
]

Customize which heading levels appear in the Paragraph Format dropdown. By default, H2, H3, and H4 are shown. All heading levels (H1-H6) are always supported in the editor content, this setting only controls what appears in the dropdown.

{
"headingLevels": [1, 2, 3, 4, 5, 6]
}
  • headingLevels - Array of heading levels (1-6) to show in the Paragraph Format dropdown. Default: [2, 3, 4]

Full toolbar with all buttons:

[
{ "name": "history", "buttons": ["undo", "redo"] },
{ "name": "text", "buttons": ["bold", "italic", "underline", "strike", "superscript", "subscript"] },
{ "name": "format", "buttons": ["textColor", "textBgColor", "inlineStyles", "inlineClasses"] },
{ "name": "paragraph", "buttons": ["heading", "bulletList", "orderedList", "blockquote", "codeBlock", "align"] },
{ "name": "insert", "buttons": ["link", "image", "video", "file", "table", "horizontalRule", "hardBreak", "htmlSnippets", "anchor"] },
{ "name": "misc", "buttons": ["clearFormatting", "codeView", "fullscreen"], "align": "right" }
]

Define custom inline styles available from the toolbar’s “Inline Styles” dropdown:

{
"inlineStyles": {
"Large": "font-size: 1.25em",
"Small": "font-size: 0.85em",
"Uppercase": "text-transform: uppercase; letter-spacing: 0.05em",
"Highlight": "background-color: yellow; padding: 0 0.25em"
}
}

The key is the label shown in the dropdown, and the value is the CSS to apply. Defaults to Large, Small, and Uppercase if not specified.

Define custom CSS classes available from the toolbar’s “Inline Classes” dropdown:

{
"inlineClasses": {
"Code": "cms-inline-code",
"Highlighted": "cms-highlighted",
"Badge": "cms-badge",
"Important": "cms-important"
}
}

The key is the label shown in the dropdown, and the value is the CSS class name to apply. Defaults to Code, Highlighted, and Badge if not specified.

Define a list of CSS class suggestions for the Block Attributes dialog. These appear as autocomplete suggestions when typing in the class field, while still allowing freeform input. Requires the blockAttributes button in your toolbar config.

{
"blockClasses": ["hero", "highlight", "card", "sidebar", "lead"]
}
  • blockClasses - Array of class name suggestions. Optional — the dialog works without it, but freeform only.

Define reusable HTML snippets that can be inserted from the toolbar. Use {content} as a placeholder for selected text:

{
"htmlSnippets": {
"Button": "<button class=\"cms-button\">{content}</button>",
"Callout": "<div class=\"cms-callout\">{content}</div>",
"Alert": "<div class=\"alert alert-warning\">{content}</div>"
}
}

Override the default color palette for text color and background color pickers. Each has its own colors array and allowCustom toggle:

{
"textColor": {
"colors": ["#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff"],
"allowCustom": true
},
"textBgColor": {
"colors": ["#ffff00", "#00ffff", "#ff00ff", "#f0f0f0"],
"allowCustom": false
}
}
  • colors - Array of hex colors for the picker. Uses a default 48-color palette if not specified.
  • allowCustom - Show native color picker for custom colors not in the palette. Default: true

Configure uploads within the editor. Each upload type has its own rules setting for validation.

{
"imagePreset": "featured",
"imageUploadRules": {
"size": { "max": 5242880 },
"filetype": ["image/jpeg", "image/png", "image/webp"]
},
"mediaUploadRules": {
"size": { "max": 52428800 },
"filetype": ["video/mp4", "audio/mpeg"]
},
"fileUploadRules": {
"size": { "max": 10485760 }
}
}
  • imagePreset - Apply a named image preset to uploaded images
  • imageUploadRules - Validation rules for image uploads (same format as Image Validation rules)
  • mediaUploadRules - Validation rules for video and audio uploads
  • fileUploadRules - Validation rules for file link uploads
{
"height": 500,
"heightMin": 300,
"heightMax": 800,
"pasteAsPlainText": true,
"charCounterCount": true,
"charCounterMax": 5000,
"wordCounterCount": true,
"wordCounterMax": 2000,
"headingLevels": [1, 2, 3, 4, 5, 6],
"toolbarConfig": [
{ "name": "history", "buttons": ["undo", "redo"] },
{ "name": "text", "buttons": ["bold", "italic", "underline", "strike", "superscript", "subscript"] },
{ "name": "format", "buttons": ["textColor", "textBgColor", "inlineStyles", "inlineClasses"] },
{ "name": "paragraph", "buttons": ["heading", "bulletList", "orderedList", "blockquote", "codeBlock", "align", "blockAttributes"] },
{ "name": "insert", "buttons": ["link", "image", "video", "file", "table", "horizontalRule", "hardBreak", "htmlSnippets", "anchor"] },
{ "name": "misc", "buttons": ["clearFormatting", "codeView", "fullscreen"], "align": "right" }
],
"inlineStyles": {
"Large": "font-size: 1.25em",
"Small": "font-size: 0.85em",
"Uppercase": "text-transform: uppercase; letter-spacing: 0.05em",
"Highlight": "background-color: yellow; padding: 0 0.25em"
},
"inlineClasses": {
"Code": "cms-inline-code",
"Highlighted": "cms-highlighted",
"Badge": "cms-badge",
"Important": "cms-important"
},
"blockClasses": ["hero", "highlight", "card", "sidebar", "lead"],
"htmlSnippets": {
"Button": "<button class=\"cms-button\">{content}</button>",
"Callout": "<div class=\"cms-callout\">{content}</div>",
"Alert": "<div class=\"alert alert-warning\">{content}</div>"
},
"textColor": {
"colors": ["#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff"],
"allowCustom": true
},
"textBgColor": {
"colors": ["#ffff00", "#00ffff", "#ff00ff", "#f0f0f0"],
"allowCustom": false
},
"imagePreset": "blog",
"imageUploadRules": {
"size": { "max": 2097152 },
"filetype": ["image/jpeg", "image/png", "image/webp"]
},
"mediaUploadRules": {
"size": { "max": 52428800 },
"filetype": ["video/mp4", "audio/mpeg"]
},
"fileUploadRules": {
"size": { "max": 10485760 }
}
}