Skip to main content

Outline

At a glance:
  • Problem: Editors can apply formatting in TinyMCE, while front-end components (Razor, React, Vue, etc.) expect controlled classes, structures, and responsive rules.
  • Objective: Ensure TinyMCE style options map directly to the organisation's design system rather than enabling arbitrary inline styling.
  • Primary mechanisms: StyleFormats, ContentCss, BodyClass, limited plugins, and block-first modelling.
  • CMS 12 PaaS principle: TinyMCE configuration is code-driven via dependency injection, not primarily managed through the Admin UI.

Introduction

Optimizely CMS 12 (PaaS) integrates TinyMCE as its rich text editor. The editor provides structured authoring capabilities but remains intentionally neutral regarding visual design. By default, TinyMCE exposes a baseline toolbar and plugin set, while Optimizely adds integration plugins for links, drag-and-drop, image editing, and other CMS-aware behaviours.

In component-driven front-end architectures, unrestricted formatting within rich text can lead to structural drift. When rich text output diverges from the design system, redesigns and refactors become content migration exercises rather than controlled UI updates.

Designing a style system that aligns with front-end components therefore requires deliberate control over:

  • The styles available in the editor
  • The HTML structures allowed in rich text properties
  • The visual parity between editor preview and front-end rendering

1. Rich text as component-compatible HTML

TinyMCE can technically produce broad HTML structures. However, front-end component systems typically expect a limited subset of predictable markup.

A sustainable alignment strategy constrains rich text to:

  • Semantic inline formatting: <strong>, <em>, CMS-managed links.
  • Controlled block structures: paragraphs, headings, lists.
  • Design-system-aligned class usage: e.g., <p class="ds-lead">, <blockquote class="ds-quote">.

Anything that represents interactive, responsive, or variant-based UI should be implemented as a block or component rather than simulated inside rich text.

Design principle: If a UI element requires behavioural logic or responsive layout rules, it should be implemented as a block or structured component - not as styled markup inside TinyMCE.

Rich text or block? A quick checklist

Select a topic to expand and read the details.

When to use rich text
  • Paragraphs, headings, and lists
  • Links and short inline emphasis
  • Simple callout text with a single design-system class
When to use blocks or components
  • Cards, accordions, tabs, forms, and CTAs with variants
  • Responsive grids and anything interactive
  • Anything with props (variant, size, icon, state) - it probably should not be free-form HTML

2. Mapping style formats to the design system

TinyMCE style formats provide the primary mechanism for aligning editor formatting with front-end components. In CMS 12, style formats are defined in code using the TinyMCE Configuration API.

A well-designed format should:

  • Apply a class already defined in the front-end design system.
  • Avoid inline CSS values (colours, spacing, pixel dimensions).
  • Use semantic tags combined with classes when necessary.

Style formats aligned with design tokens

C#
services.Configure<TinyMceConfiguration>(config => { config.For<StandardPage>(p => p.MainBody) .Toolbar("styles") .StyleFormats( new { title = "lead", block = "p", classes = "ds-lead" }, new { title = "muted", inline = "span",classes = "ds-muted" }, new { title = "callout", block = "div", classes = "ds-callout" }, new { title = "button-link", selector = "a", classes = "ds-btn ds-btn--primary" } ); });

Each format references classes that must exist in the front-end CSS bundle. The editor does not invent styling - it exposes curated styling.

Format type reference

Select a topic to expand and read the details.

block format

Applies to whole block elements (paragraph-like structures). Good for lead text, callout wrappers, and block quotes.

inline format

Applies to selected text only. Good for "muted", "highlight", "kbd", and similar inline treatments.

selector format

Applies classes to an existing element type - for example, turning an <a> into a button link without inserting layout wrappers.

Governance tip: avoid formats that insert layout <div> wrappers unless your rendering rules explicitly support them.

3. Loading editor CSS for accurate preview

Providing style formats without corresponding visual preview undermines editorial clarity. CMS 12 supports loading editor-specific stylesheets via ContentCss and scoping via BodyClass.

C#
services.Configure<TinyMceConfiguration>(config => { config.Default() .AddEpiserverSupport() .BodyClass("ds-editor") .ContentCss("/static/css/editor.css"); });

Recommended build strategy:

  • Compile design tokens and typography into both site and editor bundles.
  • Limit editor CSS to content styling (exclude navigation, layout grid, and header/footer styles).
  • Scope styles under a wrapper class to prevent leakage.

The result is a credible WYSIWYG experience aligned with production rendering.

A practical editor.css philosophy

Select a topic to expand and read the details.

What to include
  • Typography scale and link styling
  • Spacing rules for paragraphs and lists
  • Callout and quote styles
  • Table base rules (if tables are enabled) and image max-width behaviour
What to exclude and how to scope
  • Exclude: global layout grid, header/footer, navigation, app chrome, and page-level spacing systems that do not exist inside the editor iframe.
  • Always scope: prefix rules with .ds-editor so styles do not accidentally bleed into other TinyMCE contexts.

4. Explicit style definition vs automatic import

TinyMCE provides an importcss plugin that attempts to generate style options automatically from CSS. In CMS implementations, this often conflicts with explicitly defined style formats.

Explicitly defining style formats and loading editor CSS via ContentCss provides greater predictability than relying on importcss.

Recommended configuration pattern:

  • Define style formats explicitly via StyleFormats.
  • Load editor CSS explicitly via ContentCss.
  • Avoid enabling importcss unless the interaction is fully tested.

5. Enforcing guardrails through toolbar and plugins

Alignment with front-end components also requires removing formatting options that encourage inconsistency.

C#
services.Configure<TinyMceConfiguration>(config => { config.Default() .AddEpiserverSupport() .Toolbar( "blocks | bold italic | epi-link anchor | bullist numlist | removeformat", "styles") .BodyClass("ds-editor") .ContentCss("/static/css/editor.css"); });

Governance strategies include:

  • Restricting plugins to only those supported by rendering templates.
  • Minimising arbitrary formatting controls.
  • Encouraging block usage for structural components.

Guardrails that actually hold

Select a topic to expand and read the details.

Toolbar and plugin control
  • Toolbar control reduces temptation, but does not guarantee output constraints.
  • Plugin control removes entire capabilities (tables, code view, templates) when not desired.
Element rules and content modelling
  • Element rules (e.g., valid_elements) are what truly prevent unwanted markup from being stored.
  • Modelling (blocks/ContentArea) is the ultimate guardrail for anything structural or interactive.

6. Context-aware style systems using settings transforms

Multi-site or multi-brand implementations may require context-aware editor styling. The TinyMCE Configuration API supports runtime configuration modification through AddSettingsTransform.

C#
services.Configure<TinyMceConfiguration>(config => { config.Default() .AddSettingsTransform("brand-scope", (settings, content, propertyName) => { var brand = content == null ? "default" : "brand-a"; settings["body_class"] = $"ds-editor ds-editor--{brand}"; settings["content_css"] = $"/static/css/editor-{brand}.css"; }); });

This enables consistent style alignment across brands while preserving a single codebase.

7. Security and compliance considerations

Style configuration intersects with governance and compliance concerns:

  • Arbitrary inline styles increase unpredictability and complicate sanitization.
  • External resources referenced inside the editor require evaluation under security review.
  • Predictable class-based formatting reduces audit surface.

Controlled style systems therefore contribute not only to visual alignment but also to operational stability.

Conclusion

Designing style systems that align with front-end components in Optimizely CMS 12 (PaaS) requires a deliberate architecture.

A stable solution combines:

  • Explicit style formats mapped to design-system classes
  • Editor-specific CSS loaded through ContentCss
  • Scoped configuration via BodyClass and optional transforms
  • Restrained toolbar and plugin exposure

When properly implemented, rich text becomes a controlled extension of the front-end system rather than an independent formatting layer.