2026年11月13日
2026年11月13日
WordPress Sidebar Not Showing: Causes and Fixes (register_sidebar, dynamic_sidebar)
This article is a localized edition of the Japanese original. Read the Japanese original
Problems like "the sidebar does not show", "I added widgets but nothing appears" or "the widget area is missing from the Widgets screen" in WordPress usually come down to a mismatch somewhere between registering the widget area (sidebar), calling it, and placing widgets in it.
This article explains how to narrow down the cause and the code for registering and displaying sidebars correctly in a theme. The behavior of the functions was checked against the WordPress 6.9 source and the developer.wordpress.org reference (as of October 2026).
First: check what kind of theme you use
Block themes such as Twenty Twenty-Four and Twenty Twenty-Five do not use widget areas registered with register_sidebar(); their sidebars are template parts built in the Site Editor. In a theme that registers no widget areas, the "Widgets" item does not appear under "Appearance" in the admin at all.
- "Appearance" has "Editor" but no "Widgets" → it is a block theme. Add a sidebar by editing templates under "Appearance" → "Editor". The steps below do not apply.
- "Appearance" has "Widgets" → it is a classic theme (or a theme that registers widget areas). Check with the steps below.
Symptoms and causes
| Symptom | Main cause |
|---|---|
| The widget area you expect is missing from the Widgets screen | register_sidebar() is not running (wrong hook name, inside a conditional, written in another theme's functions.php) |
| Widgets are placed but not displayed | The ID passed to dynamic_sidebar() in the template does not match the id used at registration |
| The whole sidebar block is missing | The template does not call get_sidebar(), there is no sidebar.php, or is_active_sidebar() is false |
| Widgets disappeared after switching themes | The new theme's areas have different IDs, so the widgets are not assigned to any area |
Check the state with WP-CLI
If you can use WP-CLI, you can list the registered areas and the widgets placed in them.
# registered widget areas (name, id, description)
wp sidebar list
# widgets placed in an area (main-sidebar is the ID of the area to check)
wp widget list main-sidebar
# whether the area contains widgets (true / false)
wp eval 'var_dump( is_active_sidebar( "main-sidebar" ) );'
# whether the theme has sidebar.php (prints the path if it exists)
wp eval 'echo locate_template( "sidebar.php" ), PHP_EOL;'
If the area is missing from wp sidebar list, it is a registration problem; if the area exists but wp widget list is empty, no widgets are placed; if widgets exist but are not displayed, the problem is in how the template calls the sidebar.
Register the sidebar
Register widget areas with register_sidebar() in your theme's functions.php. As in the reference examples, the standard approach is to call it inside the widgets_init action.
<?php
// functions.php
add_action( 'widgets_init', 'my_theme_register_sidebars' );
function my_theme_register_sidebars() {
register_sidebar( array(
'name' => 'Main Sidebar',
'id' => 'main-sidebar', // must match the ID passed to dynamic_sidebar()
'description' => 'Shown on the right of posts and pages.',
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
) );
register_sidebar( array(
'name' => 'Shop Sidebar',
'id' => 'shop-sidebar',
'description' => 'For WooCommerce shop pages.',
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
) );
}
Points to keep in mind when registering:
- Calling
register_sidebar()directly at the top level offunctions.phpstill registers the area (it runs beforewidgets_init, so it is not "too late"). However,widgets_initis the hook provided for running widget-related setup together, so it is the safer place. - If you register inside a template file (such as
sidebar.php), that file is not loaded in the admin, so the area does not appear on the Widgets screen. - If you omit
id, it becomes a sequential ID likesidebar-1, and since WordPress 4.2 a notice asks you to set the ID. If the numbering shifts when areas are added or removed, widget assignments break, so always setidexplicitly, using lowercase letters, digits and hyphens with no spaces. - Calling
register_sidebar()automatically registers theme support forwidgets, which makes the "Widgets" item appear under "Appearance".
Display the sidebar in templates
Registering alone does not display anything. Call get_sidebar() in the theme's templates, and call dynamic_sidebar() inside sidebar.php.
sidebar.php is a file in the theme folder like this:
<?php
/**
* sidebar.php
*/
if ( ! is_active_sidebar( 'main-sidebar' ) ) {
return; // output nothing if there are no widgets
}
?>
<aside id="secondary" class="widget-area">
<?php dynamic_sidebar( 'main-sidebar' ); ?>
</aside>
Call it like this from the templates that should show the sidebar, such as single.php or page.php:
<?php
get_sidebar(); // loads sidebar.php
get_sidebar( 'shop' ); // loads sidebar-shop.php (or sidebar.php if it does not exist)
get_sidebar( 'shop' ) looks for sidebar-shop.php, then sidebar.php, and if neither exists it loads nothing and returns false. No error is shown, so check the spelling of the file name.
When you add comments around HTML, do not write PHP comments (//) outside <?php ?>. Text outside PHP tags is output to the page as is, which makes a string starting with // appear above the sidebar.
Switch sidebars by page
To use a different area depending on the type of page, add a function that returns the ID and use it from sidebar.php.
<?php
// functions.php
function my_theme_sidebar_id() {
if ( function_exists( 'is_woocommerce' ) && is_woocommerce() ) {
return 'shop-sidebar';
}
return 'main-sidebar';
}
<?php
/**
* sidebar.php (when switching)
*/
$sidebar_id = my_theme_sidebar_id();
if ( ! is_active_sidebar( $sidebar_id ) ) {
return;
}
?>
<aside id="secondary" class="widget-area">
<?php dynamic_sidebar( $sidebar_id ); ?>
</aside>
is_woocommerce() only exists when WooCommerce is active, so check with function_exists() before calling it.
Create a custom widget
Build your own widget by extending WP_Widget, and pass it to register_widget() on widgets_init.
<?php
// functions.php
class My_Recent_Posts_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'my_recent_posts',
'Recent Posts (Custom)',
array( 'description' => 'Recent posts list with a configurable count' )
);
}
// like the parent class, do not add types to the parameters
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : 'Recent Posts';
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$count = ! empty( $instance['count'] ) ? absint( $instance['count'] ) : 5;
$posts = get_posts( array(
'numberposts' => $count,
'post_status' => 'publish',
) );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
}
if ( $posts ) {
echo '<ul>';
foreach ( $posts as $p ) {
printf(
'<li><a href="%s">%s</a></li>',
esc_url( get_permalink( $p ) ),
esc_html( get_the_title( $p ) )
);
}
echo '</ul>';
}
echo $args['after_widget'];
}
// settings form in the admin
public function form( $instance ) {
$title = isset( $instance['title'] ) ? $instance['title'] : '';
$count = isset( $instance['count'] ) ? absint( $instance['count'] ) : 5;
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">Title:</label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>">Number of posts:</label>
<input class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'count' ) ); ?>" type="number" min="1" max="20" value="<?php echo esc_attr( $count ); ?>">
</p>
<?php
return '';
}
// clean up values on save
public function update( $new_instance, $old_instance ) {
return array(
'title' => sanitize_text_field( $new_instance['title'] ?? '' ),
'count' => max( 1, min( 20, absint( $new_instance['count'] ?? 5 ) ) ),
);
}
}
add_action( 'widgets_init', function () {
register_widget( 'My_Recent_Posts_Widget' );
} );
widget(), form() and update() in WP_Widget are defined in the parent class without parameter types. If you add types to the parameters in the child class, as in widget( array $args, array $instance ), PHP 8 throws a fatal error saying the method is not compatible with the parent, and the site stops loading. Without form(), the widget's settings panel only shows a note that there are no options, and you cannot enter a title or count.
Widgets when you switch themes
Widget placement is saved in the sidebars_widgets option, per area ID. When you switch themes, WordPress tries to move widgets to areas with the same ID or a similar role, but widgets it cannot move end up assigned to no area and stop showing (the widgets themselves are not deleted and can be placed again from the Widgets screen).
When you rebuild your own theme, registering the areas with the same id as before keeps the placement as is. Saving the placement before switching themes makes it easier to restore.
# save the widget placement to a file
wp option get sidebars_widgets --format=json > sidebars_widgets_backup.json
If the block widget editor does not suit you
Since WordPress 5.8, the Widgets screen of classic themes also uses the block editor. To use the old widget settings screen, activate the official Classic Widgets plugin, or disable it in your theme like this:
<?php
// functions.php
add_action( 'after_setup_theme', function () {
remove_theme_support( 'widgets-block-editor' );
} );
Summary
- Block themes have no Widgets screen. Build sidebars in the Site Editor.
- Use
wp sidebar listandwp widget listto separate registration problems from widget placement problems. - Call
register_sidebar()onwidgets_init, setidexplicitly, and use the same value indynamic_sidebar(). - Use
get_sidebar()in templates, andis_active_sidebar()withdynamic_sidebar()insidebar.php. Do not write PHP comments outside PHP tags. - Do not add parameter types to custom widget methods, and implement
form()andupdate()too.
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)