Sidebar Generator
Register widget areas with register_sidebar() and generate the template call, including the wrapper markup and the guard for an empty area.
<?php
/**
* Widget areas for the theme.
*/
/**
* Registers the widget areas.
*
* The markup here is what wraps every widget dropped into the area, so it is
* worth getting right once rather than fighting it in CSS later.
*/
function my_theme_register_sidebars() {
register_sidebar(
array(
'id' => 'sidebar-1',
'name' => __( 'Main Sidebar', 'my-theme' ),
'description' => __( 'Shown beside posts and pages.', 'my-theme' ),
'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(
'id' => 'footer-1',
'name' => __( 'Footer Column One', 'my-theme' ),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
)
);
}
add_action( 'widgets_init', 'my_theme_register_sidebars' );
/*
* Output. Put this in sidebar.php, or wherever the column belongs.
*/
if ( is_active_sidebar( 'sidebar-1' ) ) {
echo '<div class="' . esc_attr( 'sidebar widget-area' ) . '">';
dynamic_sidebar( 'sidebar-1' );
echo '</div>';
}
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Name the widget areas your theme offers, decide the markup that wraps each widget, and the generator writes the registration and the template call that skips an empty area.
How to use
- Add one area per drop zone. Three footer columns is three areas, not one area you style into columns.
- Keep the IDs stable. Widgets are stored against the area ID, so renaming it strands everything an editor already placed there.
- Set the wrapper and title tag to fit the page outline. Every widget title at
h2on a page that already has anh2is a heading order problem. - Leave the empty check on.
is_active_sidebar()keeps an empty column from leaving a gap in the layout. - Put the registration in
functions.phpand the output in the template that shows the column.
Example
One area and the output that goes with it:
function acme_register_sidebars() {
register_sidebar(
array(
'id' => 'sidebar-1',
'name' => __( 'Main Sidebar', 'acme' ),
'description' => __( 'Shown beside posts and pages.', 'acme' ),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
)
);
}
add_action( 'widgets_init', 'acme_register_sidebars' );
if ( is_active_sidebar( 'sidebar-1' ) ) {
echo '<div class="' . esc_attr( 'sidebar widget-area' ) . '">';
dynamic_sidebar( 'sidebar-1' );
echo '</div>';
}
%1$s and %2$s are filled in by WordPress with the widget ID and its classes. Dropping them breaks widget specific styling and any plugin that targets it.
Pitfalls
register_sidebar()belongs onwidgets_init. On any other hook the area may not exist when the Widgets screen is built.- Leaving out the
idmakes WordPress generate one such assidebar-1, which changes as areas are added and moves everyone’s widgets. before_widgetwithout%1$sand%2$sstrips the per widget ID and classes. Themes that do this are the reason widget CSS often does not work.dynamic_sidebar()prints nothing for an empty area, but your wrapper markup still prints. That is the gapis_active_sidebar()exists to prevent.- Unbalanced tags between
before_widgetandafter_widgetbreak the page layout for every widget at once. - Widget areas are stored per theme. Switching themes and back can leave widgets in the Inactive box.
- In a block theme the Widgets screen is replaced by template parts, so a registered sidebar may never be seen.
- A title tag chosen for looks rather than for the outline is an accessibility problem that CSS cannot fix.
Compatibility
register_sidebar(), dynamic_sidebar() and is_active_sidebar() have been stable since WordPress 2.2, and the block based Widgets screen arrived in 5.8 without changing them. Block themes use template parts instead of widget areas. The generated code targets PHP 7.0 and up, and the tool runs entirely in your browser.
Frequently asked questions
Why is my sidebar empty on the front end?
dynamic_sidebar() does not match the registered one. Both fail silently.What are %1$s and %2$s for?
before_widget or per widget styling stops working.Do widget areas work in a block theme?
Can I have several footer columns?
How do I remove a default sidebar from a parent theme?
unregister_sidebar() on widgets_init with a later priority than the parent’s registration.