Classic theme sidebars widgets
Skill Lonsdale201/wp-agent-skills/theme-development/classic-theme-sidebars-widgets
Build or audit classic theme widget areas and sidebars for WP 7.0. Covers `widgets_init`, `register_sidebar()`, stable sidebar IDs, `before_widget` and `before_title` wrappers, `dynamic_sidebar()`, `is_active_sidebar()`, `get_sidebar()`, `sidebar-{name}.php`, `show_in_rest`, semantic aside/footer/header widget areas, block-widget era compatibility, and common mistakes such as missing IDs, changing IDs after release, hardcoded widgets, bad wrapper placeholders, and rendering empty sidebars.From its SKILL.md
npx -y skills add Lonsdale201/wp-agent-skills --skill classic-theme-sidebars-widgetsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.1 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
Classic Theme Sidebars and Widgets
Use this when adding or reviewing widget areas in a classic PHP theme: blog sidebars, footer columns, header widget areas, shop sidebars, or template-specific widget regions.
In WordPress naming, "sidebar" means a registered widget area. It does not have to appear visually at the side of the layout.
When to Use This Skill
- Registering widget areas with
register_sidebar(). - Creating
sidebar.phporsidebar-{name}.php. - Rendering
dynamic_sidebar(). - Checking empty widget area behavior.
- Migrating hardcoded footer/header content to user-manageable widget areas.
- Reviewing widget markup semantics and REST exposure.
Register Widget Areas
Register widget areas on widgets_init.
add_action( 'widgets_init', 'mytheme_register_sidebars' );
function mytheme_register_sidebars() {
register_sidebar(
array(
'name' => __( 'Primary sidebar', 'textdomain' ),
'id' => 'sidebar-1',
'description' => __( 'Widgets shown beside the main content.', 'textdomain' ),
'before_widget' => '<aside id="%1$s" class="widget %2$s">',
'after_widget' => '</aside>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
'show_in_rest' => false,
)
);
}
Rules:
- Always provide an explicit
id. - Treat IDs as persistent storage keys. Changing an ID after release can orphan assigned widgets.
- Keep
%1$sand%2$sinbefore_widget; core substitutes widget ID and classes. - Choose semantic wrappers:
asidefor side content,sectionfor content regions,divonly when no semantic element fits. - Use translated
nameanddescription. register_sidebar()adds theme support for widgets.
Multiple Areas
Use predictable IDs for repeated footer columns.
for ( $i = 1; $i <= 4; $i++ ) {
register_sidebar(
array(
'name' => sprintf(
/* translators: %d: Footer column number. */
__( 'Footer column %d', 'textdomain' ),
$i
),
'id' => 'footer-' . $i,
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
)
);
}
Rules:
- Keep generated IDs stable.
- Use translator comments for numbered names.
- Do not let Customizer options or request values create arbitrary sidebar IDs.
Render a Sidebar
Use is_active_sidebar() before outputting layout wrappers.
if ( is_active_sidebar( 'sidebar-1' ) ) :
?>
<aside id="secondary" class="widget-area" aria-label="<?php esc_attr_e( 'Sidebar', 'textdomain' ); ?>">
<?php dynamic_sidebar( 'sidebar-1' ); ?>
</aside>
<?php
endif;
Rules:
- Do not output empty wrapper markup for inactive sidebars unless the layout requires a placeholder.
- Pass the sidebar ID, not a translated name.
- Do not hardcode widget output in the theme to simulate a widget area.
dynamic_sidebar()returns a boolean; use it if you need fallback behavior.
Sidebar Template Files
Use get_sidebar() to load sidebar template files.
get_sidebar(); // sidebar.php
get_sidebar( 'footer' ); // sidebar-footer.php
Rules:
- Put reusable sidebar rendering in
sidebar.phporsidebar-{name}.php. - Keep registration in
functions.php/inc/widgets.php, not in sidebar templates. - Do not make sidebar templates query-heavy; they may appear on many pages.
REST and Block Widget Era
register_sidebar() supports show_in_rest.
Rules:
- Leave
show_in_rest => falseunless the widget area must be exposed publicly through REST. - If enabling REST exposure, assume the sidebar structure is public data.
- Classic themes can still render widget areas with
dynamic_sidebar()even when the admin widget UI uses block widgets. - Do not disable block widgets just because the theme is classic unless the project has a tested compatibility reason.
Markup and Accessibility
Good widget-area output:
- Uses a landmark or labeled region when it is a major page area.
- Does not create many unlabeled
asidelandmarks. - Keeps heading levels sensible for the template context.
- Lets individual widgets output their own content.
Wrapper choice examples:
| Area | Wrapper |
|---|---|
| Blog sidebar | <aside class="widget-area"> |
| Footer column | <section class="footer-widget-area"> |
| Header utility area | <div class="header-widget-area"> or labeled <aside> |
Theme vs Plugin Boundary
Themes may register display regions. Plugins should register reusable widgets that provide business functionality.
Good theme-owned widget areas:
- Sidebar.
- Footer columns.
- Header utility region.
- Homepage display sections.
Bad theme-owned functionality:
- CRM signup logic.
- Payment/account widgets.
- Custom data dashboards.
- Anything that must survive theme switching.
Review Checklist
- Widget areas are registered on
widgets_init. - Every sidebar has an explicit stable
id. - Widget wrappers preserve
%1$sand%2$s. - Titles use appropriate heading levels.
- Template output checks
is_active_sidebar()before printing layout wrappers. dynamic_sidebar()receives IDs, not translated names.- Empty widget areas do not leave broken layout gaps.
show_in_restis intentional.- Business widgets are not implemented inside the theme.
Common Mistakes
- Omitting
idand relying on generatedsidebar-1notices. - Renaming a sidebar ID after users have assigned widgets.
- Removing
%1$sor%2$sfrombefore_widget. - Rendering empty
<aside>containers on every page. - Registering sidebars from template files.
- Using widget areas as plugin data storage.
References
- Official documentation: https://developer.wordpress.org/themes/classic-themes/functionality/sidebars/
- Official documentation: https://developer.wordpress.org/themes/classic-themes/functionality/widgets/
- Official documentation: https://developer.wordpress.org/reference/functions/register_sidebar/
- Official documentation: https://developer.wordpress.org/reference/functions/dynamic_sidebar/
- Verified source paths:
wp-includes/widgets.phpwp-includes/theme.phpwp-includes/general-template.phpwp-content/themes/storefront/sidebar.phpwp-content/themes/storefront/inc/class-storefront.phpwp-content/themes/generatepress/sidebar.phpwp-content/themes/generatepress/inc/general.php
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.