Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

WordPress 3.8 introduced in core the plugin MP6 that among other things use an iconic font called Dashicons to display fonts in the dashboard.

Now, is well know that register_post_type has an argument 'menu_icon' that allow to specify a custom icon for the CPT admin menu entry.

In my plugins/themes I often use that argument with my custom icon images that normally are dark because before 3.8 admin menu had a light background. With the default dark menu background in WP 3.8 my icons become almost invisible.

That aside, I think that use the new dashicons for my CPT will be cool.

After some research, I know I can just use the CSS from dashicons, something like

#menu-posts-mycpt div.wp-menu-image:before { content: "\f226"; }

However using both 'menu_icon' argument of register_post_type and previous css will print both icons in WP 3.8 and one icon + a strange char in WP 3.8-, and without use 'menu_icon' argument, on older versions the default icon is used.

I know I can conditionally add 'menu_icon' in register_post_type for WP 3.8- versions and conditionally add previous css for WP 3.8+, but:

  • that involves to add some code (2 conditional statements) for every CPT registered, so updating plugins/themes is quite an hard work
  • it seems to me more a workaround than an elegant solution

So, questions are:

Is possible to use dashicons css for WP 3.8+ and use custom image set up via 'menu_icon' param for previous versions in a "simpler" way that doesn't involve add 2 conditional for every CPT registered?

And, if so, is possible do that in some automagic way straight from register_post_type without any additional code?

share|improve this question

4 Answers 4

up vote 9 down vote accepted

After going through the rabbit hole and back, the answer is - yes, core does allow to easily use dashicons when registering post types and adding menu pages.

To use dashicon you need to pass its CSS class dashicons-[name] to menu_icon or icon_url in relevant places.

Classes available can be looked up in dashicons.css in source or Dashicons site (click icon and look at the name for it on top).

Alert! 3.8 seems to have released with dashicons-piechart as example of the class in inline docs, which is wrong and won't work. Actual class for that icon in release is dashicons-chart-pie.

share|improve this answer
    
I've accepted this because it's the right way to do the thing. My plugin as the benefit to be better backward compatible (and I can fix to use class names instead of char) because if you put dashicons class in menu_icon you can't use image url for previous versions... but who cares of the past ? :) –  G. M. Dec 13 '13 at 23:04

I'm answering myself because today I asked myself the 2 questions I posted, and spent some time to find an answer. Once I found a solution, I want to share it, but any other solution is higly apprecciated and I'm ready to accept any solution that I found better than mine. Edits and improvements to my solution are appreciated as well nay encouraged.


Edit

After Rarst answer I've edited the code. Now function use standard dashicons classes, but also allow to specify an old style image url in menu_icon argument and a brand new dashicons class in the menu_dashicon argument.


Workflow

First think I thought was that register_post_type, fires an action, registered_post_type, that pass to hooking functions the arguments passed to register_post_type, without filtering them, so is possible to creat custom arguments to that functions.

So I decided to pass the argument 'menu_dashicon' to pass a custom dashicon.

After that I thought to create a class that listen to that argument, saving icon in a class variable. The same class can be responsible to

  1. check the currnt version of WP, and if it is less then 3.8 do nothing
  2. if version is 3.8+ loop the $menu array on proper hook and:
  3. remove, if present, any custom images added via 'menu_icon' and
  4. add the inline style according the what is added via the 'menu_dashicon' param

I create the code in a single file, in this way it can be easily included in any theme/plugin or even used as MU plugin and after that one can just use the brand new 'menu_dashicon' argument in every theme and/or plugin installed.

I've also added a minimal plugin header that allow to use it as a standalone plugin, but probably that's the less usefull way to use.

How to use

Inside register_post_type just pass the 'menu_dashicon' argument with the value of the dashicon class (without prefix 'dashicons-'):

$args = array(
  ...
  'menu_dashicon' => 'chart-pie', // dashicons will be used in WP 3.8+
  'menu_icon' => $url_of_the_icon // icon images will be used in WP 3.7.1 & previous
);

register_post_type('my_cpt', $args);

That's all. Get Dashicons icon class name from its site.

So here the code:

<?php
/**
* Plugin Name: GM CPT Icon
*/
namespace GM;

class CptIcon {

  public static $cpt;

  public $css;

  static function registerIcon( $cpt, $icon ) {
    self::$cpt[$cpt] = $icon;
  }

  function init() {
    if ( $this->mp6() ) {
      \add_action('admin_menu', array($this, 'parseMenu') );
    }
  }

  function mp6() {
    return \version_compare( $GLOBALS['wp_version'],  '3.8', '>=' );
  }      

  function parseMenu() {
    if ( $this->mp6() && ! empty( self::$cpt ) )  {
      foreach ( $GLOBALS['menu'] as $i => $item ) {
        if  $item[1] === 'edit_posts' && (strpos($item[2], 'edit.php?post_type=') === 0)) {
          $this->menuItemClass($i, str_replace('edit.php?post_type=', '', $item[2]));
        }
      }
    }
  }

  function menuItemClass( $i, $type ) {
    if ( \in_array($type, \array_keys(self::$cpt), TRUE ) ) {
      $GLOBALS['menu'][$i][4] = str_replace('menu-icon-post', '', $GLOBALS['menu'][$i][4]);
      $GLOBALS['menu'][$i][6] = 'dashicons-' . self::$cpt[$type];
    }
  }

}

\add_action('plugins_loaded', function() {
  if ( \is_admin() && !( \defined('DOING_AJAX') && \DOING_AJAX  ) ) {
    $cpticon = new CptIcon;
    $cpticon->init();
  }
});

\add_action('registered_post_type', function( $post_type, $args ) {
  if ( isset($args->menu_dashicon) && ! empty($args->menu_dashicon) ) {
    CptIcon::registerIcon($post_type, $args->menu_dashicon);
  }
}, 10, 2);

It is also available as Gist


CPTs using dashicons

Two CPTs: "Ideas" and "Gallery" using Dashicons. Note auto color change with different admin color schemes.


share|improve this answer

Easy: Just read the the relevant part of the register_post_type() phpDocBlock and then use the right argument for menu_icon :D

  • Use the dashicons class. For e.g. dashicon-groups
  • Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme. This should begin with data:image/svg+xml;base64,.
  • Pass 'none' to leave div.wp-menu-image empty, so an icon can be added via CSS.
share|improve this answer
1  
*Dashicons class is what @Rarst says in his answer. *Using base64-encode can be useful, but imho not really straightforward, in addition svg-painer.js, the core js library used to handle color change, can be very time consuming if the icon is more "complex" then standard dashicons. *Third option (empty icon) is valid not only for WP 3.8+, but since a long time... and using css is something I want avoid (as per question). So +1 for putting all options together, but I think the accepted answer already aswer my question. P.S. happy to see that diamond near your name :) –  G. M. Jan 30 at 9:05
    
@G.M. Interesting info about the svg-painter.js file. Didn't know it as I haven't tried yet. –  kaiser Jan 30 at 11:13
1  
Once I tried to use it in a a bit complex svg image (it was a simple building plant) to create a color change effect on mouse hover. I gave up and used another approach because of too latency. –  G. M. Jan 30 at 11:34
2  
@G.M. Thanks for that one. You should write a blog post about that :) I was searching and the only useful one I could find was the one from Sven. –  kaiser Jan 30 at 11:37

I simply added this line to the code which registers the custom post type:

'menu_icon'    => 'dashicons-admin-users',

Here's the full code

enter image description here

No need to add any CSS.

share|improve this answer
    
That's the exact thing that @Rarst says in his answer... –  G. M. Dec 18 '13 at 16:20
    
Rarst doesn't provide the line of code which needs adding to the code which creates the CPT or the full snippet which i have linked to. Also there's no need for CSS so my solution is more efficient. –  Brad Dalton Dec 24 '13 at 5:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.