How to register block styles for editor and frontend (PHP and JS) in WordPress

Contents

Introduction

This article explains in detail how to register WordPress block styles for both the editor (Gutenberg) and the frontend. It covers the PHP APIs, the JavaScript APIs, the block.json workflow, how to enqueue CSS for editor and front-end, how to conditionally load styles only when blocks are present, name and class conventions, unregistering styles, and common troubleshooting tips. Code examples are provided for each technique.

What is a block style?

A block style is an alternate visual style a block can adopt. In the editor the user selects a style from the block toolbar or the block inspector in saved/post content the chosen style becomes a CSS class added to the blocks markup. The class format normally follows the pattern: is-style-{name}. For example, a style called fancy becomes is-style-fancy.

Why register block styles?

  • Expose alternative looks for core or custom blocks.
  • Allow editors to change presentation without custom CSS in the content.
  • Keep editor preview and front-end visuals consistent by loading the same styles where needed.

Naming and class conventions

  • Block name: use the full block name such as core/paragraph, my-plugin/my-block.
  • Style name: lowercase, hyphen-separated, no spaces or special chars, e.g. lead-text.
  • CSS class: WordPress adds is-style-{name} to the block wrapper when a style is selected.
  • Selector examples:
    • .wp-block-paragraph.is-style-lead-text { … }
    • .wp-block-group.is-style-card .wp-block-group__inner-container { … }

Registering block styles in PHP (server-side)

Two common PHP approaches:

  1. Use register_block_style to register a style.
  2. Register/enqueue CSS assets for editor and front-end using register_block_type or manual enqueue hooks.

register_block_style – basic usage

Use register_block_style when you want to add styles programmatically in PHP.

 fancy-quote,
            label => __( Fancy Quote, my-plugin ),
            // is_default => true, // optional: make this style the default
        )
    )

    register_block_style(
        core/paragraph,
        array(
            name  => lead,
            label => __( Lead paragraph, my-plugin ),
        )
    )
}
add_action( init, myplugin_register_block_styles )
?>

Enqueueing CSS for editor and frontend

Register the CSS files and ensure both editor and front-end load the style so the block looks the same in both places.


Registering styles via register_block_type metadata

When creating a custom block with register_block_type (or using block.json), pass style and editor_style handles. WordPress will automatically enqueue them when the block is present.

 myplugin-block-editor-script,
        editor_style  => myplugin-block-editor-style,
        style         => myplugin-block-style,
    ) )
}
add_action( init, myplugin_register_my_block )
?>

Unregistering a block style in PHP


Registering block styles in JavaScript (editor-side)

JS registration is useful when you want to register styles only for the editor or when your plugin builds assets using a bundler (wp-scripts). Use wp.blocks.registerBlockStyle or wp.blocks.unregisterBlockStyle.

Simple JS example

( function( wp ) {
    var registerBlockStyle = wp.blocks.registerBlockStyle
    var unregisterBlockStyle = wp.blocks.unregisterBlockStyle
    var domReady = wp.domReady

    domReady( function() {
        // Register a style for core/paragraph
        registerBlockStyle( core/paragraph, {
            name: lead,
            label: Lead Paragraph,
            isDefault: false
        } )

        // Unregister an existing style
        // unregisterBlockStyle( core/quote, default )
    } )
} )( window.wp )

How to enqueue the JS for the editor

Enqueue this JS file on the editor using enqueue_block_editor_assets so it runs only in the block editor.


Using block.json and build tools (preferred for modern block development)

block.json supports declaring editorStyle and style entries that point to handles which will be associated with files created by your build process. When using register_block_type_from_metadata (WordPress reads block.json), WordPress automatically registers and enqueues styles when the block is used.

Example block.json

{
  apiVersion: 2,
  name: my-plugin/my-block,
  title: My Block,
  category: widgets,
  editorScript: file:./build/index.js,
  editorStyle: file:./build/editor.css,
  style: file:./build/style.css
}

Register block using metadata


With this setup, the build outputs (editor.css and style.css) will be associated automatically, and WordPress will enqueue them when the block appears or when the editor loads.

Best practices

  • Load only whats necessary: Prefer conditional loading (has_block) or rely on block.json automatic handling so styles are only loaded when relevant.
  • Keep editor and front-end styles consistent: Use the same selectors in both CSS files one file can be reused for both if necessary.
  • Scope specificity: Target the .wp-block-… wrapper is-style-… class to avoid affecting other elements.
  • Cache busting: Use filemtime for versioning during development or proper asset versioning in build tools.
  • RTL and accessibility: Provide RTL variations if needed and ensure contrast and semantics are preserved.
  • Naming: Use unique names to avoid collisions with other plugins/themes.
  • Unregister if necessary: Provide an option or a hook so themes or other plugins can remove styles if conflicting.

Troubleshooting checklist

  • Style not appearing in editor:
    • Ensure the editor CSS is enqueued via enqueue_block_editor_assets or editorStyle in block.json/register_block_type.
    • Open the editor, inspect the block — is the is-style-{name} class present on the block wrapper?
    • Check CSS specificity — editor styles may be overridden by editor defaults.
  • Style not appearing on the front-end:
    • Confirm CSS is enqueued on the front-end (look for the stylesheet in view-source).
    • If using has_block, ensure the content where the block appears is being checked (is_singular(), etc.).
    • Server-rendered blocks must include the class in the rendered markup. If a render callback is used, ensure you dont strip classes.
  • Style applies in editor but not front-end:
    • Different file loaded for editor vs front-end — duplicate the rules or move common rules to the front-end style.
  • JS registration doesnt work:
    • Make sure the JS is enqueued for the editor and dependencies include wp-blocks and wp-dom-ready.
    • Wrap registration in domReady to ensure wp.blocks exists.

Full example: Minimal plugin that registers block styles and enqueues CSS for editor frontend

Files:

  1. my-block-styles.php (main plugin file)
  2. css/block-style.css (front-end styles)
  3. css/block-editor.css (editor-specific styles)
  4. js/editor-styles.js (optional JS to register block styles in editor)

Plugin main PHP (single-file example)

 fancy-quote,
            label => __( Fancy Quote, mbs ),
        )
    )

    register_block_style(
        core/paragraph,
        array(
            name  => lead,
            label => __( Lead Paragraph, mbs ),
        )
    )
}
add_action( init, mbs_register_block_styles )
?>

CSS: css/block-style.css (front-end)

/ Front-end style for the fancy-quote style on core/quote /
.wp-block-quote.is-style-fancy-quote {
    border-left: 4px solid #0073aa
    padding-left: 1rem
    font-style: italic
    color: #222
}

/ Front-end style for lead paragraph /
.wp-block-paragraph.is-style-lead {
    font-size: 1.25rem
    line-height: 1.5
    margin-bottom: 1rem
}

CSS: css/block-editor.css (editor styles)

/ Editor preview tweaks: scope inside the editor canvas /
.editor-styles-wrapper .wp-block-quote.is-style-fancy-quote {
    border-left: 4px solid #0073aa
    padding-left: 1rem
    font-style: italic
}

/ editor preview for lead paragraph /
.editor-styles-wrapper .wp-block-paragraph.is-style-lead {
    font-size: 1.25rem
    line-height: 1.5
}

JS: js/editor-styles.js (optional JS registration)

( function( wp ) {
    var registerBlockStyle = wp.blocks  wp.blocks.registerBlockStyle
    var domReady = wp.domReady

    if ( ! registerBlockStyle ) {
        return
    }

    domReady( function() {
        registerBlockStyle( core/quote, {
            name: fancy-quote,
            label: Fancy Quote,
            isDefault: false
        } )

        registerBlockStyle( core/paragraph, {
            name: lead,
            label: Lead Paragraph,
            isDefault: false
        } )
    } )
} )( window.wp )

Additional notes

  • If a block uses server-side rendering (render_callback), ensure the render callback preserves any style classes — WordPress will add the is-style- class to the block wrapper markup, but if you build custom markup you need to include the classes by merging them into the wrapper.
  • Block styles are best registered early (on init) so theyre available when the editor initializes.
  • To remove a style exposed by another plugin or theme, call unregister_block_style in PHP or wp.blocks.unregisterBlockStyle in editor JS during editor initialization.

References

Summary

Register block styles using register_block_style (PHP) or wp.blocks.registerBlockStyle (JS) and ensure both editor and front-end have the corresponding CSS loaded. Prefer block.json with build tooling where possible for an automated and modern workflow. Use conditional enqueueing or block.jsons automatic association to keep front-end assets performant. Always scope CSS to the block wrapper with .wp-block-… .is-style-… to avoid unintended global styling.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *