I currently have a code where, in my category.php, it checks if the specific category has subcategories, and if it does, show them using wp_list_categories.

I'd love to have these wp_list_categories to show thumbnails, so I created a new walker, but I cannot figure out how to show thumbnails.

I'd be fine with having it show the featured image of my latest custom post type in this category, or using a plugin.

I currently have the following walker in my functions.php:

 class Walker_Category_Parents extends Walker_Category {

function start_el(&$output, $category, $depth, $args) {
    global $wpdb;

    $link2 = ''.$category->slug.'';
    $cat_name = esc_attr( $category->name );
    $cat_name = apply_filters( 'list_cats', $cat_name, $category );
    $link = '<a href="' . esc_attr( get_term_link($category) ) . '" ';
    $link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
    $link .= 'rel="'.$category->slug.'" ';
    $link .= '>';
    $link .= $cat_name . '</a>';
    if ( 'list' == $args['style'] ) {
        $output .= "\t<li";

        $children = $wpdb->get_results( "SELECT term_id FROM $wpdb->term_taxonomy WHERE parent=".$category->term_id );

        $children_count = count($children);

        $has_children = ($children_count != 0) ? ' parent-category' : '';

        $class = 'cat-item cat-item-' . $category->term_id . $has_children;
        if ( !empty($current_category) ) {
            $_current_category = get_term( $current_category, $category->taxonomy );
            if ( $category->term_id == $current_category )
                $class .=  ' current-cat';
            elseif ( $category->term_id == $_current_category->parent )
                $class .=  ' current-cat-parent';
        $output .=  ' class="' . $class . '"';
        $output .= ">$link\n";
        $output .= "<img src='http://localhost/wp-content/themes/vom13/images/producten/";
        $output .= "$link2.png'>\n";
    } else {
        $output .= "\t$link<br />\n";


As you can see, it currently looks for the image in a folder, but this is absolutely not ideal, because I'm not the only one adding categories, but I don't want to give everybody FTP access.

Any solutions?



There's a great plugin called Taxonomy Images. It lets you set one image per category that you can then access in all sorts of ways.

It's a little funky in that it uses some custom filters to return the images, but the documentation is pretty good and you should be able to figure it out.

== UPDATE == Here's a quick example that gets the image based on ID (I'm assuming you'll have the $category object that you already have in your snippet:

$images = get_option('taxonomy_image_plugin');
$cat_id = $category->term_taxonomy_id;
if( array_key_exists( $cat_id, $images ) ) {
    echo wp_get_attachment_image( $images[$cat_id] );

Here's a slightly expanded version of that code on the support forums.

  • Thanks! I have looked into this plugin, but couldn't figure out how to achieve this, and wasn't sure if this was possible. I'll look into it again.
    – user31532
    Apr 16 '13 at 7:03
  • Thanks again for the edit! It shows all the images now, just not on the position I'd like them to be. (But this should be fairly easy to fix, I guess.)
    – user31532
    Apr 17 '13 at 13:39
  • It really isn't cool that you have to load a plugin to do this. I know this is an old thread, but my recommendation is to download the Taxonomy Images plugin as suggested above, open up the code, and copy what you need into your project. This way you don't have all the 'bloat' of the plugin page settings and this and that. WordPress should really make this default / standard.
    – mrwpress
    Feb 4 '20 at 18:49

I think the best way is to allow tha admin choose the featured image for a category from Media Library. This is what WooCommerce does for product categories. I checked how WooCommerce does this (in includes/admin/class-wc-admin-taxonomies.php) and here comes the reusable code (use it in functions.php or your custom plugin). It can be used with custom post types' taxonomies.

/* Image thumbnail for category */

/* If this CPT, use scripts and styles to display Media Library popup */
function media_uploader() {
    global $post_type;
    if( 'YOUR_CUSTOM_POST_TYPE' == $post_type) {
        if(function_exists('wp_enqueue_media')) {
        else {
add_action('admin_enqueue_scripts', 'media_uploader');

/*show the form field*/

add_action( 'YOUR_CUSTOM_POST_TYPE-category_add_form_fields', 'add_image_field', 10, 2 );
add_action( 'YOUR_CUSTOM_POST_TYPE-category_edit_form_fields', 'add_image_field', 10, 2 );
function add_image_field($taxonomy) {
    if(is_object($taxonomy)) // edit term not add term
    $selectedimgid = get_term_meta( $taxonomy->term_id, 'YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id', true );
    <div class="form-field term-thumbnail-wrap">
        <div id="YOUR_CUSTOM_POST_TYPE_cat_thumbnail" style="float: left; margin-right: 10px;"><img src="<?php if(isset($selectedimgid)) echo wp_get_attachment_image_src($selectedimgid)[0]; else echo "PLACEHOLDER-IMAGE-HERE.jpg";?>" width="60px" height="60px" /></div>
        <div style="line-height: 60px;">
            <input type="hidden" id="YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id" name="YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id" value="<?php if(isset($selectedimgid)) echo $selectedimgid; ?>" />
            <button type="button" class="upload_image_button button">Upload/Add image</button>
            <button type="button" class="remove_image_button button">Remove image</button>
        <script type="text/javascript">

            // Only show the "remove image" button when needed
            if ( ! jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id' ).val() ) {
                jQuery( '.remove_image_button' ).hide();

            // Uploading files
            var file_frame;

            jQuery( document ).on( 'click', '.upload_image_button', function( event ) {


                // If the media frame already exists, reopen it.
                if ( file_frame ) {

                // Create the media frame.
                file_frame = wp.media.frames.downloadable_file = wp.media({
                    title: 'Choose an image',
                    button: {
                        text: 'Use image'
                    multiple: false

                // When an image is selected, run a callback.
                file_frame.on( 'select', function() {
                    var attachment           = file_frame.state().get( 'selection' ).first().toJSON();
                    var attachment_thumbnail = attachment.sizes.thumbnail || attachment.sizes.full;

                    jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id' ).val( attachment.id );
                    jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail' ).find( 'img' ).attr( 'src', attachment_thumbnail.url );
                    jQuery( '.remove_image_button' ).show();

                // Finally, open the modal.

            jQuery( document ).on( 'click', '.remove_image_button', function() {
                jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail' ).find( 'img' ).attr( 'src', 'PLACEHOLDER-IMAGE-HERE.jpg' );
                jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id' ).val( '' );
                jQuery( '.remove_image_button' ).hide();
                return false;

            jQuery( document ).ajaxComplete( function( event, request, options ) {
                if ( request && 4 === request.readyState && 200 === request.status
                    && options.data && 0 <= options.data.indexOf( 'action=add-tag' ) ) {

                    var res = wpAjax.parseAjaxResponse( request.responseXML, 'ajax-response' );
                    if ( ! res || res.errors ) {
                    // Clear Thumbnail fields on submit
                    jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail' ).find( 'img' ).attr( 'src', 'PLACEHOLDER-IMAGE-HERE.jpg' );
                    jQuery( '#YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id' ).val( '' );
                    jQuery( '.remove_image_button' ).hide();
                    // Clear Display type field on submit
                    jQuery( '#display_type' ).val( '' );
            } );

        <div class="clear"></div>

/* and save it */

add_action( 'edited_YOUR_CUSTOM_POST_TYPE-category', 'YOUR_CUSTOM_POST_TYPE_extra_fields_save', 10, 2);
add_action( 'created_YOUR_CUSTOM_POST_TYPE-category', 'YOUR_CUSTOM_POST_TYPE_extra_fields_save', 10, 2);
function YOUR_CUSTOM_POST_TYPE_extra_fields_save( $term_id ) {

    if ( !isset( $_POST['YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id'] ) ) return;
    update_term_meta( $term_id, "YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id", $_POST['YOUR_CUSTOM_POST_TYPE_cat_thumbnail_id'] );


The way to show the image in the templates will also make use of get_term_meta():

$termimgid = get_term_meta( $term->term_id, 'thamaterial_cat_thumbnail_id', true );
    echo '<img alt="'.$term->name.'" src="'.wp_get_attachment_image_src($termimgid)[0].'" /> '.$term->name;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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