WordPress 5.8 Block-Based Widgets: Disable Classic Widgets, Filter Output, and WP_Widget Compatibility

WordPress 5.8 introduced block-based widgets — the ability to use the full block editor interface in the Widgets screen and in Theme Customizer widget areas. When a theme calls register_sidebar(), the resulting widget area can now accept blocks alongside classic widgets. Existing widgets built with WP_Widget are automatically wrapped in a “Legacy Widget” block so they continue to work, but new widget-like functionality should be built as blocks going forward. For developers, the transition requires understanding how wp_get_widget_defaults(), the widget_block_content filter, and the use_widgets_block_editor/gutenberg_use_widgets_block_editor flags interact — and how to opt specific sidebars back into the classic interface if a legacy plugin requires it.

Problem: After upgrading to WordPress 5.8 the Widgets screen shows the block editor interface. A critical third-party plugin that relies on the classic widget form interface breaks. The site also needs to filter the output of block-based widget areas to add a wrapper element.

Solution: Disable the block editor for all widget areas with use_widgets_block_editor, or use dynamic_sidebar_params to disable it per-sidebar. Filter widget area output with dynamic_sidebar_before/dynamic_sidebar_after.

<?php
// ── Option A: Revert to classic widgets for ALL sidebars ─────────────
add_filter( 'use_widgets_block_editor', '__return_false' );

// ── Option B: Keep block editor but wrap each sidebar's output ────────
// Works for both classic and block-based widget areas
add_action( 'dynamic_sidebar_before', function ( string $index, bool $has_widgets ) {
    if ( ! $has_widgets ) return;
    echo '<div class="widget-area widget-area--' . esc_attr( $index ) . '">';
}, 10, 2 );

add_action( 'dynamic_sidebar_after', function ( string $index, bool $has_widgets ) {
    if ( ! $has_widgets ) return;
    echo '</div>';
}, 10, 2 );

// ── Filter content inside each block widget ────────────────────────────
add_filter( 'widget_block_content', function ( string $content, array $instance, WP_Widget_Block $widget ): string {
    // $content is the rendered block HTML
    // Add a "widget-block" class wrapper:
    return '<div class="block-widget-inner">' . $content . '</div>';
}, 10, 3 );

// ── Register a classic WP_Widget that survives in WP 5.8+ ────────────
// Classic widgets are auto-wrapped in a "Legacy Widget" block — no code change needed
class My_Social_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct( 'my_social_widget', 'Social Links', [
            'description' => 'Social media profile links.',
        ] );
    }
    public function widget( $args, $instance ) {
        echo $args['before_widget'];
        echo $args['before_title'] . esc_html( $instance['title'] ?? 'Follow us' ) . $args['after_title'];
        $url = esc_url( $instance['twitter_url'] ?? '' );
        if ( $url ) echo '<a href="' . $url . '" rel="noopener noreferrer">Twitter</a>';
        echo $args['after_widget'];
    }
    public function form( $instance ) { /* classic form */ }
    public function update( $new, $old ) { return $new; }
}
add_action( 'widgets_init', fn() => register_widget( 'My_Social_Widget' ) );

// ── Prevent specific classic widget from showing in block widget inserter ─
add_filter( 'widget_types_to_hide_from_legacy_widget_block', function ( array $widgets ): array {
    $widgets[] = 'my_social_widget'; // hide from Legacy Widget block dropdown
    return $widgets;
} );

NOTE: Setting add_filter( 'use_widgets_block_editor', '__return_false' ) reverts all widget screens site-wide to the classic interface. If only one specific third-party plugin is the issue, check whether that plugin has been updated — most major widget plugins added compatibility for the block-based Widgets screen by late 2021. As of WordPress 6.0, the gutenberg_use_widgets_block_editor filter (used by the Gutenberg plugin) is separate from the core use_widgets_block_editor filter — you may need to apply both if the Gutenberg plugin is active.