Inline CSS plugin

This plugin is only available for paid TinyMCE subscriptions.
This feature is only available for TinyMCE 6.3 and later.

As is normal and long-time best practice, TinyMCE documents keep CSS and HTML separate. This practice is not, however, email-friendly.

The Inline CSS plugin takes a TinyMCE document, and processes it such that the previously separate CSS is applied inline to each HTML element. This single output file is much closer to the common requirements for sending as an HTML-formatted email.

Interactive example

  • TinyMCE

  • HTML

  • JS

  • Edit on CodePen

Click the button to export content with CSS inlined



Raw HTML output



Rendered output

<textarea id="inline-css" class="classic">
  <h1>TinyMCE documents and Inline CSS documents</h1>

  <h2>TinyMCE documents</h2>

  <p><em>TinyMCE</em> documents consist of</p>

  <ul>
  <li>material marked up as HTML;</li>
  <li>stylesheets defined by the <code>content_css</code> and <code>font_css</code> options; and</li>
  <li>CSS defined by the <code>style_css</code> option.</li>
  </ul>

  <h2>Inline CSS</h2>

  By contrast, <em>Inline CSS</em> documents consist of

  <ul>
  <li>a single file with all CSS styling applied inline to each HTML element.</li>
  </ul>

  <h2>The TinyMCE Inline CSS plugin</h2>

  <p>The TinyMCE Inline CSS plugin takes a TinyMCE document, with its multiple components.</p>

  <p>And returns a single file, with all CSS styling applied inline to each HTML element.</p>

  <p>As an example, below is a small text section with various styles applied. Press the <strong>Inline CSS</strong> button to view the content where all CSS are inlined</p>
  <br>
  <p class="red">Red text</p>
  <p class="red blue-background">Red text - blue background</p>
  <p class="blue">Blue text</p>
  <p class="blue red-background">Blue text - red background</p>

</textarea>

<div id="inlinecss-api-runner">
  <h1> Click the button to export content with CSS inlined</h1>
  <button id="inline-css-btn" style="margin: 10px">Inline CSS</button>
  <br/>
  <br/>

  <h2>Raw HTML output</h2>
  <textarea style="display: block; min-height: 250px; width: 100%;" id='output-text-area'></textarea>
  <br/>
  <br/>

  <h2>Rendered output </h2>
  <div style="height: 400px; display: flex; flex-direction: column; overflow: hidden;">
    <iframe style="flex: 1; height: 100%; width: 100%" id="outputIframe"></iframe>
  </div>
</div>
const settings = {
  plugins: [
    'advlist', 'anchor', 'autolink', 'charmap', 'code', 'fullscreen',
    'help', 'image', 'insertdatetime', 'link', 'lists', 'media',
    'preview', 'searchreplace', 'table', 'visualblocks', 'inlinecss'
  ],
  toolbar: 'undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image',
  content_style: `
    .red {
      color: red;
    }
    .blue {
      color: blue;
    }
    .blue-background {
      background-color: blue;
    }
    .red-background {
      background-color: red;
    }
  `
};

tinymce.init({
  selector: 'textarea.classic',
  ...settings
});

const button = document.getElementById('inline-css-btn');
const outputTextArea = document.getElementById('output-text-area');

button.addEventListener('click', () => {
  const pluginAPI = tinymce.get(0).plugins.inlinecss;
  const outputIframe = document.getElementById('outputIframe');
  const rawDoc = outputIframe.contentWindow.document;
  pluginAPI.getContent().then((content) => {
    outputTextArea.value = content.html;

    if (rawDoc) {
      rawDoc.open();
      rawDoc.write(content.html);
      rawDoc.close();
    }
  });
});

Basic setup

To add the Inline CSS plugin to the editor, add inlinecss to the plugins option in the editor configuration.

For example:

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'inlinecss',
});

Usage notes

The Inline CSS plugin does not support

  1. Pseudo-classes.

    For example:

    button:hover {
      color: blue;
    }
  2. Pseudo-elements.

    For example:

    p::first-line {
      color: blue;
    }
  3. @ rules.

    For example:

    @media (screen)
  4. The !important property.

Classic or iframe mode support

Classic or iframe mode is a sandbox. Consequently, specifying CSS is constrained.

CSS can be specified in classic mode in the following ways:

  1. The content_css option

    Setting the content_css option automatically creates the <link> tag and puts it in the TinyMCE document’s <head>.

    This is the only supported way of adding a stylesheet to TinyMCE in Classic mode.
  2. The content_style option

    Setting the content_style option automatically creates the <style> tag and puts it in the TinyMCE document’s <head>.

    This is the only supported way of adding a <style> tag to TinyMCE in Classic mode.
  3. A CSS stylesheet specified in the <head> of the iframe with a <link> tag.

    For example:

    <link rel="stylesheet" href="styles.css">
  4. A <style> tag in the <head> of the iframe.

    For example:

    <style>p { color: red; }</style>
  5. style attributes applied to specific elements within a document. That is, inline CSS

By default, TinyMCE does not support <style> tags in the document <body>.

Inline mode support

Inline mode is not sandboxed. Consequently, any specified CSS can effect how editor content presents.

CSS can be specified in inline mode in the following ways:

  1. The content_css option

    Setting the content_css option automatically creates the <link> tag and puts it in the TinyMCE document’s <head>.

    This is not recommended.
  2. A CSS stylesheet specified in the <head> of the document with a <link> tag.

    For example:

    <head>
    <link rel="stylesheet" href="styles.css">
    </head>
  3. A CSS stylesheet specified in the <body> of the document.

    For example:

    <body>
    <link rel="stylesheet" href="styles.css">
    </body>
    This is not recommended. Some browsers allow it, however, and it is, as a consequence, honored by TinyMCE when presented.
  4. A <style> tag in the <head> of the document.

    For example:

    <style>p { color: red; }</style>
  5. A <style> tag can also be manually inserted in the document <head>.

  6. style attributes applied to specific elements within a document. That is, inline CSS

By default, TinyMCE does not support <style> tags in the document <body>.

Shadow DOM support

Running a TinyMCE instance inside a Shadow DOM is not supported.

Although running neither TinyMCE nor the Inline CSS plugin in a Shadow DOM is supported, when a TinyMCE instance is in a shadow root, the Inline CSS will likely still present

as expected, whether running in Classic mode or Inline mode.

Options

The following configuration options affect the behavior of the Inline CSS plugin.

inlinecss_selector_filter

Determines whether it is valid for a given CSS selector to have its CSS properties inlined into the HTML content.

Default: All selectors are considered valid to have their CSS inlined.

Type: String RegExp or Function

inlinecss_selector_filter: (selector: string): boolean => {
  return selector.indexOf('myprefix') !== -1;
}

inlinecss_file_filter

Determines whether it is valid for a given CSS stylesheet to have its CSS inspected and inlined into the HTML content.

Default: All CSS stylesheet are considered valid to have their CSS inspected and inlined.

Type: String RegExp or Function

inlinecss_file_filter: (href: string): boolean => {
  return selector.indexOf('mystyles') !== -1;
}

Events

The Inline CSS plugin provides the following events.

The following events are provided by the Inline CSS plugin.

Name Data Description

InlineCSS

N/A

Fired when inlining the CSS begins.

APIs

The Inline CSS plugin provides the following APIs.

A new API, editor.plugins.inlinecss.getContent(); has been added to support the new InlineCSS plugin

The API’s function is to take a TinyMCE document, and processes it such that the previously separate CSS is applied inline to each HTML element. The editor.plugins.inlinecss.getContent(); API does not require configuration from the user

The API will do the following

  • Fire the 'InlineCSS' event

  • Get the editor’s content by calling the editor.plugins.inlinecss.getContent();

  • Collect all of the stylesheets defined by the content_css option

  • Collect all styles specified in the content_style option

  • Combine content_css and content_style styles while making sure content_style has a higher precedent

  • Iterate over the content within the TinyMCE editor viewport, by inlining any InlineCSS styles where it finds a selector match

  • Return an object that contains the content with InlineCSS as a string

Example

interface PluginAPI {
  getContent: () => Promise<{
    html: string;
  }>
}

Result output after the InlineCSS content has been applied by the API

{
  html: '<p style="color: red;">hello</p>'
}