Recommended Free Tools
WordPress admin icons are set differently depending on what you are changing: use the sixth argument of add_menu_page() for a new top-level plugin page, the menu_icon registration argument for a custom post type, and a target-specific approach for an existing core or third-party menu item. WordPress’s official admin icon font is Dashicons, available since WordPress 3.8.
Choose the right method first
| Target | Documented method | Best fit |
|---|---|---|
| New top-level admin page | add_menu_page() on the admin_menu hook |
Plugin or site-tool menu entries |
| Custom post type | menu_icon in register_post_type() |
The sidebar entry for your post type |
| Existing core or third-party item | Inspect the specific menu and WordPress version | Targeted customization; no universal icon API is established in the official example |
Add an icon to a new top-level admin page
Register the page on admin_menu. The icon is the sixth argument to add_menu_page(); the optional seventh argument controls menu position.
<?php
add_action( 'admin_menu', 'acme_register_tools_page' );
function acme_register_tools_page() {
add_menu_page(
__( 'Acme Tools', 'acme' ),
__( 'Acme Tools', 'acme' ),
'manage_options',
'acme-tools',
'acme_render_tools_page',
'dashicons-admin-tools'
);
}
function acme_render_tools_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
echo '<div class="wrap"><h1>' . esc_html__( 'Acme Tools', 'acme' ) . '</h1></div>';
}
The capability controls whether WordPress displays the menu, but it is also an access-control check. Keep the callback check when rendering the page. Registering the menu too early instead of through admin_menu can cause a permissions error. See the add_menu_page() reference and the Top-Level Menus handbook.
Use a Dashicon
Dashicons is WordPress’s official admin icon font. Browse the official Dashicons catalog, copy the class name including the dashicons- prefix, and pass it as the icon argument. For example, dashicons-admin-media selects the media-style icon. Do not invent class names; use one listed in the catalog. The project is licensed GPLv2-or-later with a font exception, and the documentation says it is no longer accepting icon requests.
If the icon argument is empty, WordPress falls back to the generic dashicons-admin-generic icon. Supplying a real class avoids that fallback.
Set the icon for a custom post type
A custom post type does not need another top-level page just to obtain an icon. Set menu_icon in the arguments passed to register_post_type().
Rank #2
<?php
register_post_type(
'acme_product',
array(
'labels' => array(
'name' => __( 'Products', 'acme' ),
'singular_name' => __( 'Product', 'acme' ),
),
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-products',
)
);
The value can be a Dashicons class such as dashicons-products. The register_post_type() reference documents this property.
Use an image URL or custom SVG
add_menu_page() also accepts an icon URL or a base64-encoded SVG data URI beginning with data:image/svg+xml;base64,. This is useful when no Dashicon matches your branding.
Rank #3
$icon = 'data:image/svg+xml;base64,' . base64_encode( $svg );
add_menu_page(
__( 'Acme Tools', 'acme' ),
__( 'Acme Tools', 'acme' ),
'manage_options',
'acme-tools',
'acme_render_tools_page',
$icon
);
The SVG may be colored to match the admin color scheme when it includes a fill style attribute. Keep the artwork simple and check it in every admin color scheme and WordPress version you support. For an externally or locally hosted image, pass its valid URL instead.
Passing 'none' leaves the menu image area empty so your own CSS can provide the visual treatment. That option is different from an empty value: an empty value requests WordPress’s generic Dashicon.
Rank #4
Change an existing menu item
First identify who owns the item. If it is your own top-level page, change the icon in its original add_menu_page() call. If it belongs to a custom post type, change that post type’s menu_icon argument.
For core or third-party entries, the official admin_menu hook example demonstrates accessing the global $menu and $submenu arrays to change labels. That example does not establish a general, supported recipe for replacing every existing item’s icon. Array positions and rendered markup can vary by WordPress version and by plugin, so avoid presenting a guessed index or CSS selector as universal. For a specific target, inspect that plugin’s registration code, document the WordPress version, and test the result after updates.
Quick Recap
Best Value
Common mistakes and checks
- Wrong hook: attach menu registration to
admin_menu, not an earlier hook. - Wrong argument: for
add_menu_page(), the icon is argument six; argument seven is position. - Missing prefix: Dashicons names must include
dashicons-. - Weak authorization: use a capability appropriate to the page and check it again in the callback.
- Invalid custom asset: verify that an image URL resolves and that an SVG data URI is correctly base64 encoded.
- Wrong API for the target: use
menu_iconfor a post type instead of creating an unrelated top-level page. - Theme or color issues: test custom SVGs in the admin color schemes your users actually use.
Which icon option should you choose?
| Option | Advantages | Considerations |
|---|---|---|
| Dashicons class | Built into WordPress and documented | Limited to catalog icons |
| Image URL | Uses an existing local or hosted image | Asset availability and sizing must be maintained |
| Base64 SVG | Inline asset; can participate in admin color matching with a fill style |
Requires valid encoding and testing across schemes |
'none' |
Leaves the image area for your CSS | You must supply and maintain the styling |
Official references
- Dashicons catalog and usage guide
- add_menu_page() function reference
- Top-Level Menus handbook
- admin_menu hook reference
- register_post_type() function reference
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




