WordPress List Pages With Featured Images

Published by John on July 8, 2012 Under Wordpress

I am developing a custom wordpress theme right now for a website with over a hundred pages and to make management easier, I have been using a parent/child relationship. This makes sense, as they are all related anyway and I wanted to be able to show a list of child pages, to provide easier navigation.

On the parent pages, I wanted to still be able to use wordpress’s wp_list_pages function, but wanted to use the really cool ‘featured-image’ theme option. So, I created a custom page walker, to display the images.

Basic Page Structure

The basic page structure is like the below. The “Related Picture Gallery” pages are child pages of “Main Product Page.”

Each ‘Related Picture Gallery” page has a featured image set, using the built-in wordpress option.

-Main Product Page
   -Related Picture Gallery
   -Related Picture Gallery
   -Related Picture Gallery
   -Related Picture Gallery

Add Theme Support For Featured Images

Before you can use the featured image option in the editor, you need to enable it for you theme. Add the below to your functions.php file.

add_theme_support( 'post-thumbnails' );

//optional
//set_post_thumbnail_size( 200, 142, false );

add_image_size( 'main-featured-thumbnail', 200, 142 );

The ‘add_theme_support’ function enabled the featured image option, which will then appear in the editor, bottom right of sidebar, as well as when uploading an image.

Make note of the image sizes used, in this case ‘200’ and ‘142.’ You can adjust these as needed. You can uncomment ‘set_post_thumbnail_size’ if you want to change the default thumbnail size.

Also, make note of ‘main-featured-thumbnail’ in ‘add_image_size’ . This adds a new image size, so when an image is uploaded, a version with that size is created automatically. You can change the size as needed and when you upload an image, a thumbnail with those proportions will be created.

Creating the Custom Walker

WordPress uses a base Walker class, which can be easily extended, to draw things like lists of pages and menu items. If you want to change how a menu or list is displayed, you can extend the default Walker class, in order to change how the item is displayed.

In this case, since ‘wp-list-pages’ is going to be used, it is necessary to extend the ‘Walker_Page’ class, which exists in ‘wp-includes/post-template.php.’

In your functions.php file, add the below:

class Walker_Featured_Images extends Walker_Page {
        function start_el(&$output, $page, $depth, $args, $current_page) {
                if ( $depth )
                        $indent = str_repeat("\t", $depth);
                else
                        $indent = '';

                extract($args, EXTR_SKIP);
                $css_class = array('page_item', 'page-item-'.$page->ID);
                if ( !empty($current_page) ) {
                        $_current_page = get_page( $current_page );
                        _get_post_ancestors($_current_page);
                        if ( isset($_current_page->ancestors) && in_array($page->ID, (array) $_current_page->ancestors) )
                                $css_class[] = 'current_page_ancestor';
                        if ( $page->ID == $current_page )
                                $css_class[] = 'current_page_item';
                        elseif ( $_current_page && $page->ID == $_current_page->post_parent )
                                $css_class[] = 'current_page_parent';
                } elseif ( $page->ID == get_option('page_for_posts') ) {
                        $css_class[] = 'current_page_parent';
                }

                $css_class = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );
                
                //Modification
                if(has_post_thumbnail($page->ID)){
					$image = wp_get_attachment_image_src( get_post_thumbnail_id( $page->ID ), 'main-featured-thumbnail' );
					$link_title = $link_before . '<img src="'.$image[0].'" alt="'.esc_attr( wp_strip_all_tags( apply_filters( 'the_title', $page->post_title, $page->ID ) ) ).'"/><br />'.apply_filters( 'the_title', $page->post_title, $page->ID ). $link_after;
				} else
					$link_title= $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after;
                                

                $output .= $indent . '<li class="' . $css_class . '"><a href="' . get_permalink($page->ID) . '">' . $link_title . '</a>';
				//End Modification
				
                if ( !empty($show_date) ) {
                        if ( 'modified' == $show_date )
                                $time = $page->post_modified;
                        else
                                $time = $page->post_date;

                        $output .= " " . mysql2date($date_format, $time);
                }
        }
        
       }

Note that on line #25 , a modification has been added to check if a post thumbnail has been added, using ‘has_post_thumbnail.’

If a featured image is present, ‘$link_title’ is set to display the featured image, with a caption of the post title. Otherwise, the default link title is used.

Some Notes:

– You may need to adjust sizes in the add_image_size call above.
– If you change the name used in add_image_size, ‘main-featured-thumbnail’ , make sure to also change it in wp_get_attachment_image_src
– wp_get_attachment_image_src returns the height/width of the image, so you could use that to scale or resize as needed.
– You might consider adding a default image, to be used when no thumbnail is present.

Using the Custom Walker in Your Worpdress Theme

Now that you have the walker setup, you can call wp_list_pages as normal, using the custom featured image walker. Because the class is more or less the same as the default, all of the default options should work.

In this case, since ‘wp_list_pages’ is called on a page within the loop, get_the_ID() is used to set the ‘child_of’ option.

Example Use with Base CSS:

	<div class='children_pages'>			
		<ul>
		<?php 
			wp_list_pages(array('walker'=>new Walker_Featured_Images(), 'child_of' => get_the_ID(), 'title_li'=>false));
		?>
		</ul>
	</div><!--children_pages-->

A bit of styling, adjust as needed for your theme or any other modifications.

<style>
div.children_pages ul{
margin: 0;
}

div.children_pages ul li{
background:none;
float:left;
width: 210px;
padding: 10px 20;
min-height: 210px;
text-align:center;
}

div.children_pages ul li img{
max-height: 107px;
}

div.children_pages ul li a{
margin: 0;
padding: 0;
}
</style>

9 Comments |

Comments:

  1. Niko on Aug 13, 2012

    Hi, Thanks for this.

    Can wp_list_pages be replaced by wp_nav_menu to use custom menu ?

  2. john on Aug 17, 2012

    Nico, unfortunately I do not think this would also work with wp_nav_menu, as it uses a different walker format.

    You could possibly use override the walker and copy the ‘Modification’ part above, but would need to take into account the different menu types, such as a custom menu. Perhaps when I get some time, I will do an updated post with a walker for wp_nav_menu.

  3. Eva on Aug 21, 2012

    You sir are a genius: this is the first time I found a *working* example of a way to add featured images to a page list, including childpages. Next time someone asks me about this I know where to send ’em. Thank you!

  4. john on Aug 21, 2012

    Thanks Eva, you are too generous.

    I think it is a neat way to do it though and really worked well when developing the wordpress template for this client. I am always a fan of less work in the end and being able to automatically create the navigation like this certainly made our life easier.

  5. Robbie on Nov 12, 2012

    Is there a way to pull a custom field from a page too? I see that you are accessing the Featured Image and the Page Title, and I thought it might be possible to do this as well.

  6. John on Nov 12, 2012

    Sure Robbie, you could use the $page->ID to get the custom fields within wp_list_pages.

    For instance, after line 25, you could add something like the following:

    $my_custom_field = get_post_meta($page->ID, 'my_key_name', true);
    
    if(!empty($my_custom_field)) {
    //do something with $my_custom_field
    
    }
    

    Note that this uses get_post_meta, with third Parameter, ‘single’ as =true, telling the function to return a single string.

    If you wanted an array, like if there were multiple values, you might want to use get_post_custom_values or simply leave off the third parameter. You would need to modify line 3 to replace empty with is_array and isset or something though.

  7. Robbie on Nov 12, 2012

    Thanks! But I’m kind of spotty with my php logic. I’m trying to display my custom field like the Page Title, but aren’t sure how to get there. Also, my custom field was created with the Custom Fields plugin – uses the_field(‘my_custom_field’) to get the data. Not sure if that matters. On the line where you typed “do something” I typed echo $my_custom_field (using my variable name, of course), didn’t do anything. So then on line 45, the $output variable, I added . $my_custom_field onto the end, but it didn’t do anything.

  8. Robbie on Nov 12, 2012

    Whoops! Nevermind, figured it out like 1 minute after posting. I slipped the code down right above line 45, and voila. Thanks!

  9. John on Nov 12, 2012

    Your welcome, glad you got it working!

Add a Comment