11 Hacks for the WordPress Admin Bar (Toolbar)
Since version 3.1, WordPress has introduced the "Admin Bar," the purpose of which was to provide quick access to the admin panel pages. And as of version 3.3, it slightly changed its purpose and became known as the "Toolbar." Externally and in the code, nothing has changed, but the approach has changed: now it fully supports the frontend of the site.
In this note, I will gather various techniques for modifying this toolbar: adding, modifying, removing elements, etc.
To create a toolbar in WordPress, there is a separate class WP_Admin_Bar and a number of functions. Essentially, the work of the entire toolbar is described in these two files. If you cannot find something in this article, you can try to figure it out there.
To insert code, you can use a plugin: Code Snippets
See more examples in the description of WP_Admin_Bar.
Convenient hiding of the Toolbar
Build In PostI don't like how the admin toolbar is positioned at the top in the frontend. It often doesn't harmonize with the design, but I can live with that. However, when it starts to interfere with scrolling or additional floating panels, something definitely needs to be done.
In my opinion, the most versatile solution is to make this panel collapsible. This way, it won't interfere when it's not needed.
I searched for plugins on this matter, but found some monsters. So, I had to write my own code. I like what I've come up with; in some cases, it's very convenient: not only does the panel not interfere, it can also accommodate more elements. The essence is that the panel appears when hovering over the icon in the upper left corner and it appears in a vertical view, rather than a horizontal one. It's a kind of collapsing of the admin bar.
Here's how it looks on the Twenty Twenty-One theme:
The code that makes these transformations:
<?php /** * Сollapse ADMIN-BAR (Toolbar) into left-top corner. * * @version 1.0 */ final class Kama_Collapse_Toolbar { public static function init(){ add_action( 'admin_bar_init', [ __CLASS__, 'hooks' ] ); } public static function hooks(){ // remove html margin bumps remove_action( 'wp_head', '_admin_bar_bump_cb' ); add_action( 'wp_head', [ __CLASS__, 'collapse_styles' ] ); } public static function collapse_styles(){ // do nothing for admin-panel. // Remove this if you want to collapse admin-bar in admin-panel too. if( is_admin() ){ return; } ob_start(); ?> <style id="kama_collapse_admin_bar"> #wpadminbar{ background:none; float:left; width:auto; height:auto; bottom:0; min-width:0 !important; } #wpadminbar > *{ float:left !important; clear:both !important; } #wpadminbar .ab-top-menu li{ float:none !important; } #wpadminbar .ab-top-secondary{ float: none !important; } #wpadminbar .ab-top-menu>.menupop>.ab-sub-wrapper{ top:0; left:100%; white-space:nowrap; } #wpadminbar .quicklinks>ul>li>a{ padding-right:17px; } #wpadminbar .ab-top-secondary .menupop .ab-sub-wrapper{ left:100%; right:auto; } html{ margin-top:0!important; } #wpadminbar{ overflow:hidden; width:33px; height:30px; } #wpadminbar:hover{ overflow:visible; width:auto; height:auto; background:rgba(102,102,102,.7); } /* the color of the main icon */ #wp-admin-bar-<?= is_multisite() ? 'my-sites' : 'site-name' ?> .ab-item:before{ color:#797c7d; } /* hide wp-logo */ #wp-admin-bar-wp-logo{ display:none; } /* #wp-admin-bar-search{ display:none; } */ /* edit for twentysixteen */ body.admin-bar:before{ display:none; } /* for almin panel --- */ @media screen and ( min-width: 782px ) { html.wp-toolbar{ padding-top:0 !important; } #wpadminbar:hover{ background:rgba(102,102,102,1); } #adminmenu{ margin-top:48px !important; } } /* Gutenberg */ #wpwrap .edit-post-header{ top:0; } #wpwrap .edit-post-sidebar{ top:56px; } </style> <?php $styles = ob_get_clean(); echo preg_replace( '/[\n\t]/', '', $styles ) ."\n"; } }
Now you need to copy this code into a file, include that file in functions.php, and start the class like this:
Kama_Collapse_Toolbar::init();
Another simple implementation option:
<?php /** * Vesrion: 1.0 */ add_action( 'init', [ Collapse_Admin_Bar::class, 'init' ] ); final class Collapse_Admin_Bar { public static function init(): void { add_action( 'admin_bar_init', [ __CLASS__, 'hooks' ] ); } public static function hooks(): void { // remove html margin bumps remove_action( 'wp_head', '_admin_bar_bump_cb' ); add_action( 'wp_enqueue_scripts', [ __CLASS__, 'collapse_styles' ] ); } public static function collapse_styles(): void { $styles = <<<CSS #wpadminbar { transition: clip-path .3s ease 1s, background-color .2s ease 1s; clip-path: polygon(0 0, 32px 0, 32px 100%, 0 100%); } #wpadminbar:not( :hover ) { background-color: rgba(29, 35, 39, 0); } #wpadminbar:not( :hover ) .ab-item::before { color: #1d2327; transition-delay: 1s; } #wpadminbar .ab-item { position: relative; } #wpadminbar #wp-admin-bar-site-name > .ab-item::after { content: ''; position: absolute; top: 7px; left: 7px; z-index: -1; width: 20px; height: 20px; border-radius: 50%; background-color: #fff; opacity: .8; transition: opacity .2s ease 1s; } #wpadminbar:hover #wp-admin-bar-site-name > .ab-item::after { opacity: 0; transition-delay: 0s; } #wpadminbar:not( :hover ) > * { pointer-events: none; } #wpadminbar:hover { transition-delay: 0s; clip-path: polygon(0 0, 100% 0, 100% 100vh, 0 100vh); } @media screen and ( max-width: 782px ) { #wpadminbar { clip-path: polygon(0 0, 50px 0, 50px 100%, 0 100%); } } CSS; wp_register_style( 'collapse-admin-bar', false ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion wp_add_inline_style( 'collapse-admin-bar', $styles ); wp_enqueue_style( 'collapse-admin-bar' ); } }
You need to insert this code into functions.php, or create a plugin from it if you frequently change templates.
To make the code work, the wp_footer() function must be called in the theme's footer.php.
Removing basic elements (links) from the toolbar
Build In PostI've seen a solution to this task on the internet - it's not good because the items are removed after they have been added to the panel. It would be preferable not to add them there at all. This is done as follows:
/** * Removing Basic Elements (Links) from the Toolbar. */ add_action( 'add_admin_bar_menus', 'kama_remove_default_wp_menu_items', 0 ); function kama_remove_default_wp_menu_items() { /** * For full available list: * @see WP_Admin_Bar::add_menus() * @see https://wp-kama.com/note/remove-basic-items-from-toolbar */ $remove_wp_menus_items = [ /** WordPress logo (with links). {@see wp_admin_bar_wp_menu()} */ 'wp_admin_bar_wp_menu', /** Customizer. {@see wp_admin_bar_customize_menu()} */ 'wp_admin_bar_customize_menu', /** Comments. {@see wp_admin_bar_comments_menu()} */ 'wp_admin_bar_comments_menu', /** The additional group on the right (search and account). {@see wp_admin_bar_add_secondary_groups()} */ 'wp_admin_bar_add_secondary_groups', ]; foreach( $remove_wp_menus_items as $callback ){ $priority = has_action( 'admin_bar_menu', $callback ); if( $priority !== false ){ remove_action( 'admin_bar_menu', $callback, $priority ); } } }
All available WP menu items to remove (for the code above).
$remove_wp_menus_items = [ /// User-related, aligned right. /** Internal profile menu links. {@see wp_admin_bar_my_account_menu()} */ 'wp_admin_bar_my_account_menu', /** Entire profile menu. {@see wp_admin_bar_my_account_item()} */ 'wp_admin_bar_my_account_item', /** Search. {@see wp_admin_bar_search_menu()} */ 'wp_admin_bar_search_menu', /// Site-related /** WordPress logo (with links). {@see wp_admin_bar_wp_menu()} */ 'wp_admin_bar_wp_menu', /** My sites. {@see wp_admin_bar_my_sites_menu()} */ 'wp_admin_bar_my_sites_menu', /** Sites. {@see wp_admin_bar_site_menu()} */ 'wp_admin_bar_site_menu', /** Edit site. {@see wp_admin_bar_edit_site_menu()} */ 'wp_admin_bar_edit_site_menu', /** Customize theme. {@see wp_admin_bar_customize_menu()} */ 'wp_admin_bar_customize_menu', /** Updates. {@see wp_admin_bar_updates_menu()} */ 'wp_admin_bar_updates_menu', /// Content related. /** Comments. {@see wp_admin_bar_comments_menu()} */ 'wp_admin_bar_comments_menu', /** Add post, page, media, etc.. {@see wp_admin_bar_new_content_menu()} */ 'wp_admin_bar_new_content_menu', /** Edit. {@see wp_admin_bar_edit_menu()} */ 'wp_admin_bar_edit_menu', /// Others. /** The additional group (search and account) on the right. {@see wp_admin_bar_add_secondary_groups()} */ 'wp_admin_bar_add_secondary_groups', ];
Copy elements from this array to the code above to remove menu items required for your current need.
See WP_Admin_Bar::add_menus().
Removing any elements (links) from the toolbar
It is better to remove basic elements using the method described above (however, this is not essential). This method can be used to remove additional elements added by non-WordPress plugins.
To remove, use the remove_menu() or remove_node() method — they are absolutely identical methods (aliases).
Suppose a plugin adds an item with the ID mymenu
to the menu, and we need to remove this item:
// Remove item from the toolbar add_action( 'wp_before_admin_bar_render', 'delete_item_from_toolbar', 99 ); function delete_item_from_toolbar() { global $wp_admin_bar; $wp_admin_bar->remove_menu('mymenu'); }
Removing/Disabling the Toolbar
Build In PostFirst of all, the toolbar can be disabled on the profile page and in the admin panel: Users > Profile
.
But when you need to disable it globally, use the function show_admin_bar().
See also:
- show_admin_bar - hook.
- show_admin_bar() - function.
Examples of different disabling options:
Soft Disabling
Suppose we need to disable the "Toolbar" on the front end of the site. However, we need to allow plugins to enable the toolbar through the show_admin_bar filter.
To do this, insert the following line into the theme's functions.php file:
show_admin_bar( false );
Completely Disable the Toolbar
On the front end and in the admin panel:
// Disable admin bar on the front end add_filter( 'show_admin_bar', '__return_false' ); // Disable admin bar in the admin panel remove_action( 'in_admin_header', 'wp_admin_bar_render', 0 );
Disable the Toolbar for Everyone Except Administrators (on the front end)
In this example, the toolbar is not disabled in the admin panel.
add_filter( 'show_admin_bar', 'admin_bar_for_admin_only', 99 ); function admin_bar_for_admin_only( $show_admin_bar ) { if ( $show_admin_bar && ! current_user_can( 'manage_options' ) ) { $show_admin_bar = false; } return $show_admin_bar; }
Similarly, you can disable the toolbar for any role. Instead of the capability 'manage_options'
, specify the appropriate capability for the role, see the list of capabilities here. Here are some of them:
publish_posts
- authoredit_others_posts
- editor
Disable the Toolbar for Network Administrators
add_filter( 'show_admin_bar', 'admin_bar_for_admin_only', 99 ); function admin_bar_for_admin_only( $show_admin_bar ) { if ( $show_admin_bar && ! is_network_admin() ) { $show_admin_bar = false; } return $show_admin_bar; }
And similarly, you can disable the toolbar using conditional tags or other checks.
Adding elements (links) to the toolbar
Build In PostTo add links, use the WP_Admin_Bar::add_menu() method, also known as WP_Admin_Bar::add_node(). The addition should be done on the admin_bar_menu hook.
You can add both top-level links and child links. For example, let's add a link and a child link to the toolbar:
// Adds a link to the admin bar add_action( 'admin_bar_menu', 'my_admin_bar_menu', 30 ); function my_admin_bar_menu( $wp_admin_bar ) { $wp_admin_bar->add_menu( array( 'id' => 'menu_id', 'title' => 'External Link', 'href' => 'http://example.com', ) ); // child link $wp_admin_bar->add_menu( array( 'parent' => 'menu_id', // id parameter from the first link 'id' => 'some_id', // your id to be able to add child links 'title' => 'Child Link', 'href' => 'http://example.com/subpage', ) ); }
As a result, we will get:
To change the position of the entire block of links, (put it before or after a certain block), change the number 30 — the larger the number, the closer to the end.
Another example: a child link in the site menu to the plugins page
// child link in the site menu to the plugins page if( ! is_admin() ){ add_action( 'admin_bar_menu', function ( $wp_admin_bar ) { $wp_admin_bar->add_menu( array( 'parent' => 'site-name', // id of the parent element 'id' => 'plugins_link', // your id to be able to add child links 'title' => 'Plugins', 'href' => admin_url('plugins.php'), ) ); }, 100 ); }
See the list of all possible parameters in WP_Admin_Bar::add_menu().
Icon (dashicon) for admin bar
Build In PostFor doing this you need additional to dashicons
class add ab-icon
class to HTML element specified in title
attribute. Let's look at such example:
add_action( 'admin_bar_menu', 'add_toolbar_link', 70 ); function add_toolbar_link( $wp_admin_bar ){ $wp_admin_bar->add_menu( [ 'id' => 'chartlink', 'title' => '<span class="ab-icon dashicons-visibility"></span><span class="ab-label">Views</span>', 'href' => '#', ] ); }
As a result, we will get:
Dashicons can be found here: https://developer.wordpress.org/resource/dashicons/
How to find the $id of an existing toolbar element
To find the $id of an existing panel element in order to remove it or to add a child element to it, look at this ID in the source code: it is added as a suffix in the id attribute of the LI tag: wp-admin-bar-{ID}
:
You can also find the element in the code of WordPress or a plugin, but this is more difficult.
Removing only the top margin from the toolbar
To ensure that the toolbar is displayed correctly, WordPress adds a 28px margin to the HTML and BODY tags. If this margin needs to be removed for some purposes, use this code:
add_action( 'admin_bar_init', function(){ remove_action( 'wp_head', '_admin_bar_bump_cb' ); // html margin bumps } );
This option removes the function that adds CSS styles.
Adding a custom menu to the toolbar
Build In PostThis feature can be practically indispensable because, in addition to convenience, it also adds functionality.
By using the following code, we register the navigation menu wp_nav_menu and add items from this menu to the toolbar.
/** * toolbar nav menu - навигационное меню в тулбаре * v0.3 */ add_action( 'after_setup_theme', function() { register_nav_menu( 'toolbar', 'Toolbar' ); } ); add_action( 'admin_bar_menu', 'kama_add_toolbar_menu', 999 ); function kama_add_toolbar_menu( $toolbar ) { $locations = get_nav_menu_locations(); if( ! isset( $locations['toolbar'] ) ){ return; } $items = wp_get_nav_menu_items( $locations['toolbar'] ); if( ! $items ){ return; } foreach( $items as $item ){ $args = [ 'parent' => $item->menu_item_parent ? 'id_' . $item->menu_item_parent : false, 'id' => 'id_' . $item->ID, 'title' => $item->title, 'href' => $item->url, 'meta' => [ 'class' => implode( ' ', $item->classes ), 'title' => esc_attr( $item->description ), 'target' => $item->target, ], ]; $toolbar->add_node( $args ); } }
How it works.
You add the code to functions.php. Then go to the admin panel: Appearance > Menus
and create a menu, add any links to it, and attach the menu to the "Toolbar" area. You can use multiple levels, then the top level will be the main in the toolbar, and the additional ones will become a dropdown list.
Link to delete a post in the toolbar
The link to edit a post is always in the toolbar. But if posts are often deleted on the site, it is convenient to have a link for deletion, so you don't have to navigate to the post editing page for deletion.
add_action( 'admin_bar_menu', 'kama_delete_toolbar_link', 90 ); function kama_delete_toolbar_link() { global $wp_admin_bar; if ( ! is_super_admin() || ! is_admin_bar_showing() ){ return; } $obj = get_queried_object(); if ( ! $obj || ! isset( $obj->post_type ) ){ return; } $dellink = get_delete_post_link( $obj->ID ); if( $dellink ){ $wp_admin_bar->add_menu( array( 'id' => 'delete', 'title' => EMPTY_TRASH_DAYS ? 'Move to Trash' : 'Delete Post', 'href' => $dellink, ) ); } }
Here, 90 means after the edit link (which is 80).
Always show the toolbar
A rare case, but such a need may arise. This code will always display the toolbar, even when the user is not logged in. But in this case, only the "Login" link will be displayed. It is specified in the code. By analogy, you can add some other links there:
// Always show the admin bar add_filter( 'show_admin_bar', '__return_true' , 1000 ); add_action( 'admin_bar_menu', 'pjw_login_adminbar', 0 ); function pjw_login_adminbar( $wp_admin_bar) { if ( is_user_logged_in() ){ return; } $wp_admin_bar->add_menu( [ 'title' => 'Login', 'href' => wp_login_url() ] ); remove_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 ); }
Replace "Hello" with "Greetings" in the toolbar
The informal word "Hello" displayed in the admin bar may not be suitable for all sites. Sometimes it needs to be replaced, let's do it:
add_action( 'admin_bar_menu', 'replace_wordpress_howdy', 25 ); /** * Replaces "Hello" with "Greetings" in the toolbar. * * @param WP_Admin_Bar $wp_admin_bar */ function replace_wordpress_howdy( $wp_admin_bar ) { $my_account = $wp_admin_bar->get_node( 'my-account' ); if ( isset( $my_account->title ) ) { $newtext = str_replace( 'Hello,', 'Greetings,', $my_account->title ?? '' ); $wp_admin_bar->add_node( [ 'id' => 'my-account', 'title' => $newtext, ] ); } }
Multisite: move out sub-sites menu to the main menu of the Admin bar
If you have a multisite with only a few sub-sites, it is much more convenient to put all sub-sites in the main toolbar menu.
GitHub<?php /** * Сutomize multisite admin bar. * Moves default nested multisite menu to main toolbar menu. */ class Multisite_Admin_Bar { public static function init(): void { add_action( 'admin_bar_menu', [ __CLASS__, 'cutomize_toolbar' ], 31 ); // 31 - after `wp_admin_bar_site_menu()` add_action( 'wp_head', [ __CLASS__, 'styles' ] ); add_action( 'admin_head', [ __CLASS__, 'styles' ] ); add_action( 'admin_bar_menu', [ __CLASS__, 'add_switch_node' ], 30 ); } public static function styles(): void { ?> <style id="cutomize_multisite_admin_bar"> #wp-admin-bar-network-admin .ab-icon:before{ color:#797c7d; } /* the color of the main icon */ #wpadminbar .hl-current-blog{ background-color: rgba(255 255 255 / 0.15); } </style> <?php } public static function cutomize_toolbar( \WP_Admin_Bar $toolbar ): void { // for multisite only if( ! $toolbar->get_node( 'site-name' ) ){ return; } // remove Multisite Language Switcher hook remove_action( 'admin_bar_menu', [ \lloc\Msls\MslsPlugin::class, 'update_adminbar' ], 999 ); // NOTE: the closure needed to access `WP_Admin_Bar->nodes` private property $callback = function(){ $nodes = & $this->nodes; // @phpstan-ignore-line /// remove nodes unset( $nodes['site-name'], // default current site node $nodes['my-sites-super-admin'], $nodes['my-sites'], $nodes['my-sites-list'] ); /// network-admin $net_admin = & $nodes['network-admin']; $net_admin->parent = ''; $net_admin->title = '<span class="ab-icon dashicons-admin-multisite"></span><span class="ab-label">Network</span>'; /// blogs foreach( $nodes as $key => $node ){ preg_match( '/blog-(\d+)(?:-(\w+))?/', $node->id, $mm ); $blog_id = (int) ( $mm[1] ?? 0 ); $type = $mm[2] ?? ''; if( $blog_id ){ // main: blog-1, blog-2 if( ! $type ){ // title preg_match( '~^<.*>~', $node->title, $mm ); $lang = langdata()->blog_id_lang( $blog_id ); $title_icon_html = $mm[0] ?? ''; $flag_img = sprintf( '<img src="%s" alt="%s">', langdata()->flag_url( $lang ), $lang ); $node->title = $title_icon_html . $flag_img . ' ' . strtoupper( $lang ); $node->href = is_admin() ? get_home_url( $blog_id ) : $node->href; $node->parent = ''; $node->meta['class'] = ( get_current_blog_id() === $blog_id ) ? 'hl-current-blog' : ''; } // comments: blog-1-c, blog-2-c if( 'c' === $type ){ unset( $nodes[ $key ] ); } } } }; $callback = $callback->bindTo( $toolbar, \WP_Admin_Bar::class ); $callback->call( $toolbar ); } public static function add_switch_node( \WP_Admin_Bar $toolbar ): void { global $pagenow; $url = $_SERVER['REQUEST_URI']; $url = str_starts_with( $url, '/ru' ) ? preg_replace( '~^/ru~', '', $url ) : "/ru$url"; if( 'post.php' === $pagenow && ( $post_id = (int) ( $_GET['post'] ?? 0 ) ) ){ $other_post_id = is_ru() ? get_ru_en_post_id( $post_id ) : get_en_ru_post_id( $post_id ); $url = $other_post_id ? str_replace( "post=$post_id", "post=$other_post_id", $url ) : ''; } $toolbar->add_menu( [ 'id' => 'switch_langs', 'title' => '<span class="ab-icon dashicons-controls-repeat"></span>', 'href' => $url, 'meta' => [ 'title' => 'Switch Curent Page to Opposite Lang', 'onclick' => 'alert("aaaaaaaaa")', ], ] ); } }
Plugins for the admin bar (toolbar)
-
Clicky by Yoast - integrates a web analytics service into the admin bar.
-
What The File - an excellent plugin for studying the template hierarchy. It shows which template file is responsible for displaying the current page you are on. The information is displayed in the admin bar.
-
Admin Bar Disabler - allows you to remove the bar for specified roles: white and black lists. Or for specified capabilities: the possibility can also be placed in white and black lists. In general, this is a plugin for total customization of the admin bar.
- Menu item adding generator - service