TinyMCE

The rich text editor behind great content creation experiences.

The Most Advanced WYSIWYG HTML Editor | TinyMCE


Rich Text Editor
...see more

Want to give users more visual control over their content without extra complexity? TinyMCE already includes built-in tools for changing text color and background (highlight) color—you just need to enable them.

These tools are ideal for short articles, notes, or mini-blogs where users want to emphasize key ideas or improve readability.

What this enables:

  • Text color selection
  • Background highlight color
  • A user-friendly color picker UI
  • No custom plugins or UI needed

How to enable it:
Add forecolor and backcolor to the toolbar configuration.

tinymce.init({
  selector: '#editor',
  plugins: 'lists link code',
  toolbar: 'undo redo | bold italic underline | forecolor backcolor | code'
});

That’s all. TinyMCE automatically provides a color picker that works well for beginners and advanced users alike.

Why this works well:

  • Quick to implement
  • Low maintenance
  • Improves content clarity and expression
...see more

iving users unlimited color options can quickly lead to inconsistent or hard-to-read content. TinyMCE allows you to define a custom color palette, so users stay within visual guidelines while still having creative freedom.

This is especially useful for platforms with shared feeds, collaborative writing, or brand-focused content.

Benefits of a custom color palette:

  • Consistent visual style
  • Better readability
  • Alignment with brand colors
  • Fewer design mistakes

How to define custom colors:
Use color_map to control which colors appear in the picker.

tinymce.init({
  selector: '#editor',
  plugins: 'lists link code',
  toolbar: 'undo redo | bold italic underline | forecolor backcolor | code',

  color_map: [
    '000000', 'Black',
    'FFFFFF', 'White',
    '1E293B', 'Dark Blue',
    '2563EB', 'Primary Blue',
    '16A34A', 'Green',
    'F59E0B', 'Orange',
    'DC2626', 'Red'
  ],

  color_cols: 4
});

Users will now see only these predefined colors, making content look more cohesive across the platform.

When to use this approach:

  • Shared or public content feeds
  • Brand-driven platforms
  • Editorial or knowledge-based sites
...see more

Sometimes one color palette just isn’t enough. Text colors usually need to be dark and readable, while highlight colors should be soft and subtle. By default, TinyMCE uses the same color palette for both—but with a small customization, you can fully separate them.

By replacing the built-in color buttons with custom toolbar buttons, you gain complete control over which colors are available for text and which are used for background highlights. This approach is ideal for platforms that care about accessibility, readability, and consistent visual design.

What this approach enables:

  • Dark, high-contrast colors for text
  • Soft, low-saturation colors for highlights
  • Full control over labels, order, and UX
  • Clear separation of purpose for each color picker

How it works:
You register two custom menu buttons—one for text color and one for background color—and apply styles manually using editor commands.

tinymce.init({
  selector: '#editor',
  toolbar: 'textcolorpicker highlightpicker',
  setup: (editor) => {

    editor.ui.registry.addMenuButton('textcolorpicker', {
      text: 'Text Color',
      fetch: (callback) => {
        callback([
          { type: 'choiceitem', text: 'Black', value: '#000000' },
          { type: 'choiceitem', text: 'Blue', value: '#2563EB' },
          { type: 'choiceitem', text: 'Red', value: '#DC2626' }
        ]);
      },
      onItemAction: (api, value) => {
        editor.execCommand('ForeColor', false, value);
      }
    });

    editor.ui.registry.addMenuButton('highlightpicker', {
      text: 'Highlight',
      fetch: (callback) => {
        callback([
          { type: 'choiceitem', text: 'Yellow', value: '#FEF08A' },
          { type: 'choiceitem', text: 'Light Blue', value: '#DBEAFE' },
          { type: 'choiceitem', text: 'Light Green', value: '#DCFCE7' }
        ]);
      },
      onItemAction: (api, value) => {
        editor.execCommand('HiliteColor', false, value);
      }
    });

  }
});

When to use this approach:

  • Shared or public content feeds
  • Editorial or knowledge platforms
  • Accessibility-focused designs
  • Strict brand or design systems

Why it’s worth it:
Although this requires a bit more setup, it’s currently the only reliable way to enforce different color rules for text and highlights in TinyMCE—without confusing users or sacrificing flexibility.

...see more

Code highlighting improves readability and helps readers understand examples faster. When using TinyMCE together with Highlight.js, many developers notice that JavaScript highlighting works, but JSON or plain text does not. This problem is common—and luckily easy to fix once you know where to look.

The first step is using the correct language identifiers in TinyMCE. The values defined in codesample_languages must match the language names that Highlight.js understands. JavaScript works because it is included by default, but JSON and plain text need special attention.

TinyMCE configuration

codesample_languages: [
  { text: 'Plain Text', value: 'plaintext' },
  { text: 'JSON', value: 'json' },
  { text: 'JavaScript', value: 'javascript' }
]

Next, make sure Highlight.js actually loads the required languages. Some builds do not include JSON or plain text automatically, so they must be added manually.

Highlight.js setup

<link rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/vs.min.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/json.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/plaintext.min.js"></script>

<script>
  hljs.highlightAll();
</script>

Finally, remember that TinyMCE content is often added dynamically. Highlight.js only runs once by default, so new code blocks must be highlighted again after rendering.

Re-run highlighting

document.querySelectorAll('pre code')
  .forEach(el => hljs.highlightElement(el));

With the correct language values, loaded modules, and proper initialization, JSON and plain text code blocks will highlight reliably and look consistent across your site.

Comments