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.

I use the Categories widget on my sidebar(s) and I would like to display a Font Awesome icon next to each category listed in the widget. The icon would be the same for all categories, for now, but I would like to give each category it's own unique icon in the future.

I would like to modify the Categories widget using code in my functions.php file to add the icon by inserting markup like <i class="fa fa-chevron-right"></i> into category's link/anchor element after the category's title. I could accomplish this via CSS, but in doing so I lose the ability to programmatically determine which icon to display, along with the flexibility for other improvements/changes that I may wish to make in the future.


Basically, I wish to achieve this effect:

Cat 1          >

Cat 2          >

Cat 3          >

(The greater-than symbol '>' represents the icon placement relative to the category title)


I have Font Awesome enqueued in the functions.php file using the wp_enqueue_scripts hook as follows, and it loads and displays the icons perfectly. Note that I do not use any Font Awesome plugin built for WordPress.

/* Enqueue Scripts
-----------------------------------------------------------------*/
add_action( 'wp_enqueue_scripts', 'essentials_enqueue_scripts' );
function essentials_enqueue_scripts() {
    /* jQuery */
    wp_enqueue_script('jquery');
    wp_enqueue_script( 'jquery_ui', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://ajax.googleapis.com/ajax/libs/jqueryui/2.0.3/jquery-ui.min.js", false, null);
    wp_enqueue_script( 'waypoints', get_template_directory_uri() . '/js/waypoints.min.js');
    wp_enqueue_script( 'essentials_main', get_template_directory_uri() . '/js/essentials_main.js', array(), '1.0.0', true );
    wp_enqueue_script( 'essentials_show_stuff', get_template_directory_uri() . '/js/essentials_show_stuff.js', array(), '1.0.0', true );
    /* Google Fonts */
    wp_register_style('GoogleFonts','http://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800|Bad+Script');
    wp_enqueue_style( 'GoogleFonts');
    /* Font Awesome Fonts */
    wp_register_style('Font Awesome','//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
    wp_enqueue_style( 'Font Awesome'); 
}

Despite my best research efforts, I was unable to find a solution to modify the categories widget.

share|improve this question
1  
Please clarify your question to explain how it is WordPress-specific, rather than merely CSS. Also, please edit your question to include what you have done/tried so far. How are you including/enqueueing the FontAwesome font? –  Chip Bennett Jan 4 at 14:05
1  
"This is WordPress specific due to me wanting to customize WordPress categories via the FUNCTIONS.PHP file" - given that the ultimate solution is still entirely CSS, the question still isn't WordPress specific. It merely happens in the context of WordPress. Your limitation of wanting a function to pop into functions.php, which excludes the most plausible answers, also makes this question too localized. Perhaps if you edited the question to focus on how to enqueue custom CSS, it would be on-topic for WPSE? –  Chip Bennett Jan 6 at 21:04
1  
The CSS content attribute isn't a background image, it's content. And a CSS solution is the best way to implement - even if you want to expose end-user options. What I'm trying to help you see is that your unnecessary and arbitrary constraints are making the problem unnecessarily difficult. –  Chip Bennett Jan 7 at 0:53
1  
"I do not really wish to have to put 25 lines of code into my CSS to display the different icons." - the real problem with this is that it makes your question too localized, because you restrict the best and most obvious solution: CSS. I simply can't fathom why 25 lines of CSS is less-desirable than multiple filters, and 50 lines of PHP string-replacement. –  Chip Bennett Jan 7 at 14:54
1  
"I don't know why we are still battling over something that has been answered." - because Stack Exchange sites are not support forums, but Question and Answer sites intended to build a knowledge base for general/universal application. Your arbitrary limitation makes the question not universally useful, which is why it renders the question as too localized. And while you're free to accept whatever answer best suits your needs personally, the accepted answer is, quite frankly, terrible for the vast majority of people who need to incorporate icon fonts. –  Chip Bennett Jan 7 at 16:35
show 11 more comments

4 Answers

up vote 4 down vote accepted
+100

Assumptions:

You don't explain how you want to install the Font Awesome package, so I just assume for the moment that you use the plugin Font Awesome Icons.

You wrote:

Before anyone says use a background image, I do not want to do that. I would like it to be physical.

so I assume you want to use the <i> tag directly, for example:

<i class="fa icon-caret-right"></i>

after each category link in the widget category list.

Idea:

You can use the wp_list_categories filter to modify the output of the widget category list.

Example:

Here is a simple example how to inject it into the category list via the wp_list_categories filter:

/**
 * Inject Font Awesome <i> tag after each widget category link
 *
 * @param string $output
 * @return string $output
 */

 function custom_wp_list_categories( $output )
 {  
     remove_filter( current_filter(), __FUNCTION__ ); 
     return str_ireplace( '</li>', '<i class="fa icon-caret-right"></i></li>', $output);
 }

 add_action( 'widgets_init', function(){
     add_filter( 'wp_list_categories', 'custom_wp_list_categories' );
 });

This will give you an output similar to this one:

catlist

share|improve this answer
1  
Not going to downvote a legitimate solution/attempt to help the OP, but really: using PHP string-replacement when a simple CSS rule would suffice seems to be overkill. –  Chip Bennett Jan 6 at 21:05
1  
@MrJustin thanks for the voting, I'm also impressed by the ingenious answers provided by the other users. ps: \s* matches any whitespace character, like space, tab and newline. –  birgire Jan 6 at 22:53
2  
@MrJustin could you please expand your question to detail these "future needs" for which CSS is insufficient? As it stands your question is specifically regarding CSS and is not tied to WordPress, and as such is sitting on shifty grounds for being closed as off-topic. –  boscho Jan 7 at 2:43
2  
I might also add that a WordPress filter was excessive enough given the scope of MrJustin's question. I hardly think leading him into regular expressions is a good idea... I can't help but feel regular expressions lie polar opposite to the simplicity of a static CSS implementation. I fear for any future WPSEpedian who comes here looking to display a single character out of an icon-font and winds up with a chunk of regular expressions in their backend. Have pity on the n00bs! –  boscho Jan 7 at 2:47
2  
one could also use: return str_ireplace( '</a>', ' <i class="fa fa-chevron-right"></i></a>', $output); –  birgire Jan 7 at 5:40
show 7 more comments

This answer contains a fairly simple CSS solution.

Essentially, you'd add the following to your stylesheet:

.cat-item cat-item-7 {
     list-style-image: url('my-epic-news-icon');
}


cat-item cat-item-11 {
     list-style-image: url('my-epic-jquery-icon');
}

etc

Yes, it's not a very dynamic solution, but your categories aren't likely to change I suppose.

share|improve this answer
2  
That the answer is pure CSS is indicative of the underlying question being off-topic for WPSE. That said: I think your CSS selectors do not have proper syntax. You should use .cat-item.cat-item-7 - or, since the same icon font image is intended to be used for all list items, just use .cat-item. Also: a font icon would use the content attribute, and would target the :after pseudo-class, such as: .cat-item:after { content: '\f18d'; }. –  Chip Bennett Jan 4 at 14:25
    
Fair points. Yes I made a mistake in the syntax. Are we sure OP wants the same image, or different one per category? (That's how I understood it). I just wanted to propose the easiest solution, although that does take the qu/answer off-topic. –  Strap1 Jan 4 at 14:32
1  
Not the solution I was looking for as I had said I didn't want to use a background and that I would want the icon after the text. While it may not be a background, it's still an image, and not Font Awesome. Good solution, but not the solution for me. –  MrJustin Jan 4 at 23:35
add comment

Assuming that you want to use the fa-chevron-right icon, you simply need to target the list item via CSS. Use the :after pseudo-class:

.list-item:after {
    font-family: FontAwesome; // or whatever the font awesome family is registered as
    content: '\f054';
}

Edit

So, to give an idea of how you might pass dynamic CSS (which can be easily adapted to a custom Plugin option) via a callback, here's an example:

(Note: "plugin" and "theme" are interchangeable below.)

First, we'll modify the CSS to target list items inside of a Widget specifically. WordPress adds a class, .widget, to the Widget container. So you can target that:

.widget .list-item:after {}

Or, if this will all be wrapped up in a Plugin that registers a custom Widget, then you can target the CSS class that you define in your custom Widget, via the $widget_ops array:

$widget_ops = array( 
    'classname' => 'custom-widget-classname', 
    'description' => __( 'Custom Widget Description', 'namespace' ) 
);

So, you can target that custom classname:

.custom-widget-classname .list-item:after {}

Or, if you want to target the core "Categories" Widget, you can use the .widget_categories class. We'll go with that approach for the example.

We're going to put it inside a callback, hooked into wp_head, though you can just as easily use wp_print_styles:

function pluginslug_fontawesome_styles() {
    // Code will go here
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );

Inside, we're just going to output a stylesheet, with our rule from above:

function pluginslug_fontawesome_styles() {
    ?>
<script type="text/css">
.widget_categories .list-item:after {
    font-family: FontAwesome; // or whatever the font awesome family is registered as
    content: '\f054';
}
</script>
    <?php
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );

At this point, you're done. Easy peasy. But, since you're already inside a PHP function, you can easily make this stylesheet dynamic, by using a variable:

function pluginslug_fontawesome_styles() {

    // Define list-style icon variable
    $list_item_icon = '\f054';

    // ...snip:
    content: <?php echo $list_item_icon; ?>;

So now, it's a simple matter to use a custom Plugin option value, just by passing it to the variable:

function pluginslug_fontawesome_styles() {

    // Get Plugin options, assumed to be an array
    $plugin_options = get_option( 'pluginslug_plugin_options' );

    // Define list-style icon variable
    $list_item_icon = $plugin_options['list_item_icon'];

    // Output stylesheet
    ?>
<script type="text/css">
.widget_categories .list-item:after {
    font-family: FontAwesome; // or whatever the font awesome family is registered as
    content: <?php echo $list_item_icon; ?>;
}
</script>
    <?php
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );

So that's it! Dynamic CSS, outputting an actual icon (not a background image), pulling from a Plugin option.

And since it's just CSS, it's easily extensible to pretty much any selector you can imagine - not just limited to a list item inside of a Widget.

share|improve this answer
    
Very nice option, but I wanted a function. :) –  MrJustin Jan 6 at 20:42
    
You know that you can wrap up CSS rules in a callback, and enqueue at wp_head or wp_print_styles, right? But that part of the implementation is a separate question and outside of the scope of the question as-written. –  Chip Bennett Jan 6 at 21:01
    
Yes I do know how to enqueue. However, I don't want to use CSS. I know it's a quick and efficient way of doing it, and I do compliment you on that.. but maybe I should be using the words 'need a' instead of 'want a' when it comes to the function. –  MrJustin Jan 6 at 21:19
    
Please see the edited question. I added an example to show how the entire thing really can be handled via CSS, dynamically, extensibly, and able to account for custom Plugin options. –  Chip Bennett Jan 7 at 1:16
    
Right, but now, what if I wanted to have the 'icon' float to the right? In my normal CSS I have attached it to li a:after {content} and tried: text-align: right and it did nothing for me. What I mean by this, to clarify, is what if I wanted all of the icons on the right of the LI with the text on the left. Say the ul/li was set to 250px, the text is always a link, but I had it set to block. Then I added the 'icon' and wanted the icon to sit to the right of the li. With the <i...></i> I can easily float it. –  MrJustin Jan 7 at 1:30
show 1 more comment

I would do it like this:

// If you're using the widget only on specific pages,
// you might want to use some appropriate conditions here
add_action('wp_enqueue_scripts', function() {
    wp_enqueue_style('font-awesome',
        '//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
});

function wpse_128247_font_awesome_categories($cat_name) {
    // Define your desired icon here
    $icon = ' <i class="fa fa-smile-o"></i>';

    return $cat_name.$icon;
} // function wpse_128247_font_awesome_categories

function wpse_128247_add_filter($cat_args) {
    add_filter('list_cats', 'wpse_128247_font_awesome_categories');

    // Since we're hijacking this filter, we just pass through its data
    return $cat_args;
} // function wpse_128247_add_filter
add_filter('widget_categories_args', 'wpse_128247_add_filter');

function wpse_128247_remove_filter($output) {
    remove_filter('list_cats', 'wpse_128247_font_awesome_categories');

    // Since we're hijacking this filter, we just pass through its data
    return $output;
} // function wpse_128247_remove_filter
add_filter('wp_list_categories', 'wpse_128247_remove_filter');

First, we enqueue the font awesome styles. Then, we hijack some filters to add/remove our own filter for the category listing. That's it.


// EDIT:
Without the comments, adapted to the fact that you already have enqueued Font Awesome, using closures, and letting the filter remove itself, the code reads like the following:

function wpse_128247_font_awesome_categories($cat_name) {
    remove_filter(current_filter(), __FUNCTION__);
    return $cat_name.' <i class="fa fa-smile-o"></i>';
} // function wpse_128247_font_awesome_categories

function wpse_128247_add_filter($cat_args) {
    add_filter('list_cats', 'wpse_128247_font_awesome_categories');
    return $cat_args;
} // function wpse_128247_add_filter
add_filter('widget_categories_args', 'wpse_128247_add_filter');

I would not call that overkill. But yes, my code consists of more lines than birgire's current solution.

share|improve this answer
    
Your solution wasn't bad, but an overkill compared to birgire's. I already have Font-Awesome enqueued, sorry I didn't specify. –  MrJustin Jan 6 at 20:41
1  
Yeah, that code is not an overkill, I will agree with that. It probably just looked like more with the 4 functions instead of 2, and the amount of commenting. I appreciate the commenting, I'm not downing that. It just looked like a lot more :). –  MrJustin Jan 7 at 1:26
add comment

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.