How to Add Custom Post Type Icons

I recently updated Portfolio Press to use new icons for its custom post type. The previous icon worked fine, but it didn’t exactly match the rest of WordPress core. I was also lucky enough to have Ben Dunkle, the designer who created the current set of core WordPress icons, offer to make me a new one.

[Note, I no longer recommend including custom post types from a theme. Here’s my Portfolio Post Type plugin on GitHub if you want to see example code]

I have a zip file of the icons I used (in psd format) which also has some other options we considered (briefcase, nicer weird eyeball) and the png files of the final choice. Feel free to use this in your own projects that need a portfolio icon. You can download it here.

There’s also a great collection of free custom post type icons available here for download which might have other icons you might be looking for.

How to Add Custom Post Type Icons to Your Theme

Custom Post Type Icons

There’s two ways to add an icon to a custom post type. The easiest, is just to declare it when you register the post type:

'menu_icon' => [YOUR FILE PATH HERE] . '/images/portfolio-icon.png',  // Icon Path

This works well, except it doesn’t allow you any options for the hover or active states. If you want a different icon to be used in those cases you need to add the icon as a css style rather than registering it using the above method. This was the code I used to make the icon appear in Portfolio Press:

// Styling for the custom post type icon

add_action( 'admin_head', 'wpt_portfolio_icons' );

function wpt_portfolio_icons() {
    ?>
    <style type="text/css" media="screen">
        #menu-posts-portfolio .wp-menu-image {
            background: url(<?php [YOUR FILE PATH HERE] ?>/images/portfolio-icon.png) no-repeat 6px 6px !important;
        }
	#menu-posts-portfolio:hover .wp-menu-image, #menu-posts-portfolio.wp-has-current-submenu .wp-menu-image {
            background-position:6px -16px !important;
        }
	#icon-edit.icon32-posts-portfolio {background: url(<?php [YOUR FILE PATH HERE] ?>/images/portfolio-32x32.png) no-repeat;}
    </style>
<?php }

If you look at the files in Portfolio Press, or in the zip, you’ll see the two smaller icons 16×16 were combined in one .png file sprite. The first two styles in the above code block set those. (That’s the one circled in blue in the above screenshot). One for the regular state, and one for the active state.

The third style is for the 32×32 icon that appears in the post index (circled in red). You actually won’t be able to use this until 3.1 is released (http://core.trac.wordpress.org/ticket/14959) but since I already had the icons ready I thought I would release it anyways and when you upgrade you’ll get a nice surprise.

Note that my registered custom post type is “portfolio”. If you’ve registered something else, your style rules will be different. (e.g. #menu-posts-posttype .wp-menu-image).

About Devin

I am a developer based in Austin, Texas. I run a little theme shop called DevPress and help manage a WooCommerce shop with Universal Yums. Find me on twitter @devinsays.

10 Responses

  1. Barbara

    Hi Devin,
    I have a weird problem. When I add the 32×32 icon to my custom post type – it displays properly but the Media Uploader breaks and only displays a white screen. Take it out, and everything works perfectly.

    Latest version 3.3.1, no plugins installed. Any idea how this could be causing a conflict with the media uploader?

  2. Hello Devin,

    Just wanted to thank you for sharing the love (knowledge) on this one. Albeit the normal pin does the job, I think the details make the world and this was a small nuisance I had when I added custom posts.

    GREAT JOB!!!

  3. I think there is an inbuilt option now. Here is how it works

    Example:

    get_stylesheet_directory_uri() . ‘/images/reviews_icon.png’
    ));

    While registering custom post types itself we can define the icon. Thank you.

  4. Allister

    Use of get_stylesheet_directory_uri() is important if you use a child theme, as the old bloginfo(‘template_url’) gives you the parent theme directory.

Leave a Reply to Gabriel Reguly Cancel reply