Listing the Child Pages of a Parent Page Using a Shortcode

I am not a big fan of shortcodes. They tend to tie users into themes or plugins. However, we were in need of a way to display subpages on a parent page without modifying a template. For that a shortcode came in handy.

Have you ever created a parent page simply to organize data? I am sure most of us have. For those of you that have not, here is an example. You manage a baseball team and you have a parent page named ‘Team Members’ with positions as the child pages. You then go a step further and organize the players by position; thus, creating grand-child pages. This is obviously an effective method of organizing players.

Remember that parent page? What information goes on it? Why not a list of all the team members? As a good idea as this sounds, most individuals would simply hardcode the team members onto the page. This poses an obvious problem. Each time the player list or position changes, you have to update the page.

A much better solution is to have the pages populate when changes are made. This can easily be achieved with php, but requires either a modification of a template file or a shortcode. As hard as it is for me to say this, the latter is the better choice.

The Shortcode

Now that the decision is made, let’s create the shortcode.

//Add a shortcode for listing child pages of a parent page
function list_pages_shortcode( $atts ) {
	// Basic shortcode markup
	extract( shortcode_atts( array(
		'post_parent' => false,
		'title' => '',
	), $atts ) );

	//If the post parent attribute isn't specified, use the current post's ID
	if ( ! $post_parent ) {
	global $post;
		if ( is_object( $post ) ) {
			$post_parent = $post->ID;
		} else {
			return false;

	//Build the arguments - we want the child of the post_parent
	$args = array(
		'depth'		   => 3,
		'child_of'     => $post_parent,
		'title_li'     => $title,
		'echo'         => 0,
		'sort_column'  => 'menu_order, post_title'

	// if there is no title lets barf up the wordpress pages instead
	if ( empty( $title ) ) {
		return "<ul>" . wp_list_pages( $args ) . "</ul>";
	} else {
		return wp_list_pages( $args );
add_shortcode( 'list_subpages', 'list_pages_shortcode' );

Once you have added this to your theme, simply add the following shortcode to the page where you want to list its subpages.


Code Explained

Well actually, I am not going to get into detail over the actual code; however, there is a parameter you can pass within the shortcode itself.

Let’s say you want to list subpages of a particular page that is not the parent page. You can do this like so by adding that page’s ID to the shortcode. Here is an example.

[list_subpages post_parent="3"]

This allows you to list a page and its subpages on any page or post.

I hope you find this shortcode useful. Fell free to expand as needed.

This will only work with post-types with a hierarchal structure


  1. kw · February 2, 2012

    Didn’t work for me. :( No PHP errors or anything, just… not doing anything, haha.

  2. Stuart · February 2, 2012

    Brilliant thank you.
    Found this after numerous searches and other attempts.
    Works a treat and saves adding another plugin!
    Thank you for sharing.

  3. Cory · February 2, 2012

    This is great code, thanks for sharing! I didn’t want to install a plugin for something so simple, so this worked well (just had to add it to my already-existent shortcodes.php file). Thank you! :)

  4. James Reader · February 2, 2012

    How can I specify a class name for each item listed?

    • Justin Kopepasah · February 2, 2012

      That can be a bit tricky. Are you trying to apply different styles to each item or just trying to apply the same styles to all the items?

      • James Reader · February 2, 2012

        Same style for all.

        Also, can we include thumbnails of each page’s featured image?

        • Justin Kopepasah · February 2, 2012

          You can add class to the <ul> element.

          With the method (wp_list_pages) above you are not able display the featured image. However, it is about time that I update this post with a better way to list the child pages. Check back later for an update. :)

          • James Reader · February 2, 2012

            I’ll be watching.