Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Adding custom styles to WordPress’s Visual editor involves two separate jobs: loading CSS so the editing canvas resembles your site, and registering named formats that authors can choose from a toolbar menu. Use add_editor_style() for editor-preview CSS, theme.json for standard styles in block themes, and TinyMCE’s styleselect/style_formats configuration when writers need a selectable format such as “Notice box.”

First decide what “custom style” means

Use the approach that matches the result you need:

Need Best approach Where it applies
Make text, links, spacing, and other content look like the front end while editing Editor stylesheet loaded with add_editor_style() Classic TinyMCE; also the block editor when a classic theme declares editor-styles support
Define site-wide colors, typography, elements, or block defaults in a block theme theme.json Global styles, elements, and individual blocks; users can adjust supported values in Appearance > Editor > Styles
Give authors a dropdown choice such as “Lead paragraph” or “Notice box” TinyMCE styleselect plus style_formats, backed by matching CSS Classic editor’s Visual toolbar

Loading a stylesheet alone does not create a toolbar option. Conversely, registering a format without defining its CSS leaves the editor and front end with an unstyled class.

Load an editor stylesheet in the classic editor

1. Create the stylesheet in the active theme

In the active theme’s root directory, create editor-style.css (the default filename) or another CSS file. Keep selectors focused on content rather than WordPress admin controls:

body#tinymce.wp-editor {
    font-family: system-ui, sans-serif;
    margin: 10px;
}

body#tinymce.wp-editor a {
    color: #1464a0;
}

.notice-box {
    border-left: 4px solid #1464a0;
    padding: 1rem;
    background: #eef6ff;
}

2. Register it from functions.php

function my_theme_editor_styles() {
    add_editor_style( 'editor-style.css' );
}
add_action( 'after_setup_theme', 'my_theme_editor_styles' );

add_editor_style() looks for the path relative to the theme root and links the file to TinyMCE when it exists. It accepts a string or an array; if you omit the argument, WordPress uses editor-style.css.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Child themes and alternate filenames

With a child theme, WordPress checks the child and parent theme locations for the same relative path. Put the child theme’s replacement file at that path when you need to override the parent’s editor styling. If you use another filename, pass it explicitly to add_editor_style().

Make a classic theme’s Gutenberg canvas match the site

The block editor handles editor styles differently from TinyMCE. In a classic theme, declare editor-styles support before loading the stylesheet:

function my_theme_block_editor_styles() {
    add_theme_support( 'editor-styles' );
    add_editor_style( 'style-editor.css' );
}
add_action( 'after_setup_theme', 'my_theme_block_editor_styles' );

Use selectors that describe the content being edited. Gutenberg scopes styles to its content area and can rewrite a body { ... } rule to target .editor-styles-wrapper. Avoid broad resets: rules intended for the whole front end can unintentionally restyle editor controls, block inserters, or other administration UI.

This method is for a classic theme that uses Gutenberg. It is not a substitute for registering a toolbar format; it only loads the visual rules.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use theme.json in a block theme

For a block theme, place standard design-system values in theme.json rather than maintaining parallel CSS wherever WordPress supports the setting. The top-level styles property can define global values, individual elements, and individual blocks:

{
  "version": 2,
  "styles": {
    "color": {
      "text": "#222222",
      "background": "#ffffff"
    },
    "elements": {
      "button": {
        "color": {
          "text": "#ffffff",
          "background": "#1464a0"
        }
      }
    },
    "blocks": {
      "core/quote": {
        "typography": {
          "fontStyle": "italic"
        }
      }
    }
  }
}

What belongs in each level?

  • Global styles: defaults such as overall text and background colors.
  • Elements: HTML-oriented parts such as buttons.
  • Blocks: rules for a specific block, such as the core quote block.

This approach exposes supported values in Appearance > Editor > Styles, so site owners can adjust the design system without editing PHP or CSS. Keep custom, one-off classes outside theme.json when they are not represented by a standard global, element, or block setting.

Add a selectable style to the Visual toolbar

To let authors choose a format, register the class and turn on TinyMCE’s hidden Styles dropdown. Add the following to a classic theme or a site-specific plugin:

function my_mce_buttons( $buttons ) {
    array_push( $buttons, 'styleselect' );
    return $buttons;
}
add_filter( 'mce_buttons_2', 'my_mce_buttons' );

function my_mce_formats( $init ) {
    $init['style_formats'] = wp_json_encode([
        [
            'title'   => 'Notice box',
            'block'   => 'div',
            'classes' => 'notice-box',
            'wrapper' => true,
        ],
        [
            'title'   => 'Lead paragraph',
            'block'   => 'p',
            'classes' => 'lead',
        ],
    ]);
    return $init;
}
add_filter( 'tiny_mce_before_init', 'my_mce_formats' );

Keep the markup and CSS in sync

The class in style_formats must exactly match the class in the editor stylesheet and the front-end stylesheet. “Notice box” creates a div with notice-box; “Lead paragraph” creates a paragraph with lead. The wrapper option controls whether TinyMCE wraps the selected content in the specified block.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

After applying a format, switch to the editor’s code view or inspect the generated markup. TinyMCE style behavior can vary with configuration, so verify that the expected element and class are produced in the target editor.

Understand TinyMCE’s CSS options

TinyMCE distinguishes between two ways to style editable content:

  • content_css loads one or more external stylesheets into classic iframe content.
  • content_style injects inline CSS into the editable area.

Both affect the content area, not the surrounding toolbar or WordPress administration UI. In a theme, add_editor_style() is the usual WordPress integration; direct TinyMCE options are useful when a plugin owns the editor configuration or needs inline rules.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot a missing or inaccurate preview

The stylesheet is not loading

  • Confirm the filename and path are relative to the active theme root.
  • Check that the file exists in the child theme when a child theme is active.
  • For plugin-hosted CSS, use the documented URL or filter-based approach rather than assuming a theme-relative path.
  • Clear browser, page-cache, and optimization-plugin caches after changing editor assets.

Gutenberg ignores the styles

In a classic theme, verify that add_theme_support( 'editor-styles' ) runs before add_editor_style(). Then inspect the block editor canvas and confirm that your selectors target content rather than admin chrome.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The dropdown is absent

Loading CSS does not enable the menu. Confirm that styleselect is added through mce_buttons_2 and that style_formats is supplied through tiny_mce_before_init. Another plugin may also filter these values, so inspect the final toolbar configuration if your code is present but the control is still missing.

The menu appears but the style has no effect

Compare the class character-for-character in three places: the TinyMCE format definition, the editor stylesheet, and the front-end stylesheet. Also verify that the format’s element type and wrapper match the content you selected.

The editor controls look broken

Remove or narrow global resets. A reset shared with the front end can affect Gutenberg controls and other editor UI; prefer content-specific selectors and conservative defaults.

The preview is stale

Clear browser and plugin caches, reload the editor, and inspect the iframe (classic) or block canvas (Gutenberg) to confirm that the latest asset is present.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended implementation by editor and theme

Editor/theme combination Implement first Add only when needed
Classic editor with a classic theme add_editor_style() and an editor CSS file TinyMCE Styles dropdown for named formats
Gutenberg with a classic theme add_theme_support( 'editor-styles' ) followed by add_editor_style() TinyMCE registration only if the site still exposes a classic Visual editor workflow
Gutenberg with a block theme theme.json for supported global, element, and block styles Additional CSS for genuinely custom classes or effects

Test both the editing canvas and the published page. The editor preview is a development aid, not proof that front-end styles, responsive behavior, or plugin output are identical.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.