[wp-trac] [WordPress Trac] #39558: A lot of menu classes (and id's) are missing when there's no menu set for a location

WordPress Trac noreply at wordpress.org
Thu Jun 4 12:53:45 UTC 2026


#39558: A lot of menu classes (and id's) are missing when there's no menu set for a
location
---------------------------+------------------------------
 Reporter:  benoitchantre  |       Owner:  (none)
     Type:  enhancement    |      Status:  closed
 Priority:  normal         |   Milestone:  Awaiting Review
Component:  Menus          |     Version:  4.7
 Severity:  normal         |  Resolution:  wontfix
 Keywords:                 |     Focuses:  template
---------------------------+------------------------------
Changes (by terraGirl):

 * status:  new => closed
 * resolution:   => wontfix


Comment:

 @SergeyBiryukov Edith here, working on Contributor Day at WCEU. This
 ticket interests me, as I've worked with the menu walkers but wasn't aware
 of this fallback quirk. Please let me know if you agree with closing this.

 == Behaviour summary

 When `wp_nav_menu()` falls back to `wp_page_menu()` because no menu is
 assigned to a theme location, the rendered `<li>` items receive a
 different and smaller set of CSS classes than items in a properly assigned
 nav menu. Theme developers cannot use a single CSS selector to style both
 cases.

 '''Fallback output:'''
 {{{
 class="page_item page-item-42 current_page_item"
 }}}

 '''Normal nav menu output:'''
 {{{
 class="menu-item menu-item-type-post_type menu-item-object-page menu-
 item-42 current-menu-item current_page_item"
 }}}

 == Root cause

 `wp_nav_menu()` in `src/wp-includes/nav-menu-template.php#L167-L170`
 short-circuits immediately when no menu is found and calls the fallback:

 {{{
 if ( ( ! $menu || is_wp_error( $menu ) || ( isset( $menu_items ) && empty(
 $menu_items ) && ! $args->theme_location ) )
     && isset( $args->fallback_cb ) && $args->fallback_cb && is_callable(
 $args->fallback_cb ) ) {
         return call_user_func( $args->fallback_cb, (array) $args );
 }
 }}}

 This early return bypasses:
 - `_wp_menu_item_classes_by_context()` at line 201 — which sets `menu-
 item`, `menu-item-type-*`, `menu-item-object-*`, and all `current-menu-*`
 classes
 - `Walker_Nav_Menu` entirely

 The default `fallback_cb` is `wp_page_menu` `src/wp-includes/nav-menu-
 template.php#L74`. That function calls `wp_list_pages()` which uses
 `Walker_Page`, producing the `page_item` / `page-item-{ID}` /
 `current_page_*` class family instead.

 '''Class comparison:'''

 ||= Class =||= Normal menu =||= Fallback =||
 || `menu-item` || ✓ || ✗ ||
 || `menu-item-type-post_type` || ✓ || ✗ ||
 || `menu-item-object-page` || ✓ || ✗ ||
 || `menu-item-{ID}` || ✓ || ✗ ||
 || `current-menu-item` || ✓ || ✗ ||
 || `current-menu-ancestor` || ✓ || ✗ ||
 || `current-menu-parent` || ✓ || ✗ ||
 || `menu-item-has-children` || ✓ || ✗ ||
 || `page_item` || ✓ (via compat) || ✓ ||
 || `page-item-{ID}` || ✓ (via compat) || ✓ ||
 || `current_page_item` || ✓ || ✓ ||
 || `current_page_ancestor` || ✓ || ✓ ||
 || `current_page_parent` || ✓ || ✓ ||


 == Scope

 - **Affected:** Classic themes using `wp_nav_menu()` with the default
 `fallback_cb => 'wp_page_menu'`. Covers TwentyTen through TwentyTwentyOne
 and any custom classic theme.
 - **Not affected:** FSE themes (TwentyTwentyTwo+, WordPress 5.9+). They
 use the Navigation block, which falls back to `core/page-list` — an
 independent rendering path that already outputs `current-menu-item`,
 `current-menu-ancestor`, and `has-child` using its own logic.
 - **Confirmed reproducible** in TwentyTwenty, TwentyFourteen and
 TwentyEleven with no menu assigned to the `primary` location.


 == Recommendation

 Whilst the wish to have a uniform approach to menus is understandable, I
 recommend closing as "won't fix" as the impact on existing themes is
 signficant. A fix would change a standard approach in classic themes used
 for the past 16 years, resulting in CSS styles being applied to menus that
 never had them before. Good backwards compatibility is not possible.

 I recommend to also close
 https://core.trac.wordpress.org/ticket/18842

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/39558#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list