How to Disable Default WordPress Widgets (Code, Plugin, or Whitelist)

Date:

WordPress still registers a dozen legacy widgets, but on a modern site most of the clutter is now blocks. Here is what each method actually removes, tested on a current install.

The short answer: To disable default WordPress widgets, call unregister_widget() for each one on the widgets_init hook. That removes them from the classic Widgets panel and from the Legacy Widget block. On the default, block-based Widgets screen, though, the Calendar, RSS and Tag Cloud you see are blocks, and unregister_widget() leaves them alone; hide those with the allowed_block_types_all filter, scoped to the Widgets editor. A widget-management plugin can do the legacy half from the dashboard.

What the Widgets screen looks like now

Since WordPress 5.8, Appearance → Widgets is a block editor. Two things follow from that, and both surprised us when we tested on a fresh install with a classic theme (Twenty Twenty-One; block themes have no Widgets screen at all):

  • The Legacy Widget block already hides most core widgets. WordPress keeps a list of widgets that have a block equivalent (Archives, Calendar, Categories, RSS, Search, Tag Cloud, Text and others) and leaves them out of its dropdown. On our install the dropdown offered just Meta and Navigation Menu.
  • What you actually see in the inserter’s Widgets group are blocks: Archives, Calendar, RSS, Tag Cloud, Latest Posts and the rest.

The old list of every widget only comes back if you install the official Classic Widgets plugin. Knowing which screen you’re on decides which method works.

Unregistering a widget hides the legacy widget. On the block-based Widgets screen, the block of the same name stays.

Method 1: one snippet for the legacy widgets

The most direct method is to unregister each widget on the widgets_init hook. Add this to a small site plugin or your child theme’s functions.php:

function disable_core_widgets() {
    unregister_widget( 'WP_Widget_Calendar' );
    unregister_widget( 'WP_Widget_Meta' );
    unregister_widget( 'WP_Widget_RSS' );
    unregister_widget( 'WP_Widget_Tag_Cloud' );
}
add_action( 'widgets_init', 'disable_core_widgets' );
Code language: PHP (php)

You do not need priority 11, which a lot of tutorials insist on. WordPress registers its own widgets before it fires widgets_init, and only builds the widget objects later, at priority 100, so the default priority works. We ran the snippet at the default priority with the Classic Widgets panel on: the four widgets disappeared, taking the list from 18 to 14.

Two screenshots of the Available Widgets panel on a WordPress site using the Classic Widgets plugin. On the left, before the snippet, 18 widgets are listed, including Calendar, Meta, RSS and Tag Cloud. On the right, after the unregister_widget snippet runs at the default priority, those four are gone and 14 widgets remain.

Each widget is a class name (WP_Widget_Pages, WP_Widget_Archives, WP_Widget_Categories, WP_Widget_Recent_Posts, and so on), so you remove exactly the ones you name.

Hiding the block versions too

On the default block-based Widgets screen, that same snippet changes nothing you can see: the Calendar, RSS and Tag Cloud blocks are still in the inserter. To hide them there, filter the allowed blocks for the Widgets editor only:

add_filter( 'allowed_block_types_all', function ( $allowed, $context ) {
    if ( 'core/edit-widgets' !== $context->name ) {
        return $allowed; // posts and pages keep every block
    }
    $all = array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() );
    // Widget Area and Widget Group exist only in the browser, so add them back explicitly.
    $all = array_merge( $all, array( 'core/widget-area', 'core/widget-group' ) );
    return array_values( array_diff( array_unique( $all ), array( 'core/calendar', 'core/rss', 'core/tag-cloud' ) ) );
}, 10, 2 );
Code language: PHP (php)

The context check matters: without it you would remove those blocks from the post editor as well. With it, our post editor still offered all three blocks while the Widgets screen did not.

Two crops of the block inserter's Widgets group on the block-based Widgets screen. On the left, after the unregister_widget snippet alone, Calendar, RSS and Tag Cloud are still offered next to Archives, Latest Posts, Page List, Search and the rest. On the right, after the allowed_block_types_all filter scoped to the Widgets editor, Calendar, RSS and Tag Cloud are gone and the other widget blocks, including Legacy Widget and Widget Group, remain.

Method 2: a plugin, when you’d rather not code

A widget-management plugin gives a non-developer the same switch from the dashboard. We tried Widget Disable (under Appearance → Disable Widgets). It works, but it follows the same rules as WordPress: on the block-based Widgets screen it offered only the two widgets the Legacy Widget block still shows, and the full list of 18 appeared only once Classic Widgets was on. It also has a tab for dashboard widgets, which is a different job.

The Widget Disable plugin's settings page twice. On the default block-based Widgets screen its Sidebar Widgets list offers only Meta and Navigation Menu. With the Classic Widgets plugin active the same list offers all 18 core widgets, from Archives to Video, each with a checkbox.

So a plugin is a good fit for a classic-widgets site managed by a non-developer. On a block-widgets site, it won’t touch the blocks.

Code gives you a permanent, reviewable result; a plugin gives a non-developer a safe switch. Pick for who maintains it.

Method 3: whitelist instead of blacklist

If you only want to keep two or three widgets, invert the logic: let core register its widgets, then unregister any that aren’t on your keep-list. You maintain one short array of the classes you want, and every other default widget is removed automatically, so a future WordPress version that adds a new default widget won’t quietly appear in your panel. The same idea works for blocks: return a short allow-list from the allowed_block_types_all filter above instead of subtracting from the full list.

Which method should you use

  • The snippet when you use the Classic Widgets panel or want legacy widgets gone for good, in version control.
  • The snippet plus the block filter on the default block-based Widgets screen, where the clutter is blocks.
  • A plugin when a non-developer manages a classic-widgets site and needs a dashboard toggle.
  • A whitelist when you want a small, fixed set and new defaults kept out automatically.

All of them are reversible: remove the code, re-check the box, or add the name back to the keep-list.

The short version

On today’s WordPress, Appearance → Widgets is a block editor. unregister_widget() on widgets_init (default priority is fine) removes legacy widgets from the Classic Widgets panel and the Legacy Widget block, but the Calendar, RSS and Tag Cloud blocks stay; hide those with allowed_block_types_all, scoped to the core/edit-widgets context so the post editor is untouched. Plugins such as Widget Disable follow the same rules, so they suit classic-widgets sites. A keep-list works for both widgets and blocks.

Frequently Asked Questions

Will disabling a widget break my theme’s layout?

No. Unregistering a widget only removes it from the list of available widgets. Any widget already placed in a sidebar keeps rendering as it was; you are hiding options, not editing your live sidebars.

Why does Calendar still show after I unregistered it?

Because what you see is probably the Calendar block. On the block-based Widgets screen, unregister_widget() removes the legacy widget, which WordPress was already hiding from the Legacy Widget block. Use the allowed_block_types_all filter for the Widgets editor to hide the block.

Do I need priority 11 on widgets_init?

No. Core registers its widgets before widgets_init fires and instantiates them later, at priority 100. We tested the snippet at the default priority and it removed all four widgets.

Does disabling default widgets speed up my site?

Barely. Fewer registered widgets means slightly less to load in the admin; front-end speed is essentially unchanged. Treat it as a tidiness and control measure.

What’s the easiest method for a beginner?

On a classic-widgets site, a widget-management plugin with checkboxes. On the default block-based screen, the honest answer is the snippet plus the block filter, because plugins of this kind only reach the legacy widgets.

Share post:

Subscribe

Popular

More like this
Related

How to Merge Spreadsheets by URL (and Why Our Tool Reported 5 Misses That Weren’t)

Matching two spreadsheets on a URL column is the same job as matching a stock list to a price list by product code. It goes wrong in the same two places: how you clean the code, and how you count what didn't match.

Many-to-One: Why a Mapping Backlog Outgrows Its Target Taxonomy

You're mapping a messy source vocabulary onto a clean target taxonomy. The target has about 5,600 slots, so the job must be roughly 5,600 decisions — right? The backlog is already past 8,900, and still climbing.

The Fix That Didn’t Take: When a Content-Hash Gate Skips Your Code Change

You shipped a fix to how one field is computed, re-ran the pipeline across everything, and it reported a clean run. Then the consistency check still flags those records as wrong. The fix is in the code, the rebuild "ran" — and the records never changed. Your own optimisation skipped them.

Your Dedup Scan Is Over-Counting — Because It Forgot What You Already Fixed

The report said 80 duplicate groups still to resolve. You'd been resolving them for days. You run it again after a big batch and it *still* says 80-ish. The backlog isn't stubborn — the scan is counting work you already finished.