In this tutorial we will show you how to get child pages in WordPress with WP Query. We will show how to loop though all child pages of a current page and print out the result.
Contents
The easiest way to do this is with functions (the correct way will be with plugins). In function.php of our theme we’ve added code to make the output we wanted.
global $post; $child_pages_query_args = array( 'post_type' => 'page', 'post_parent' => $post->ID, 'orderby' => 'date DESC' ); $child_pages = new WP_Query( $child_pages_query_args );
while ( $child_pages->have_posts() ) : $child_pages->the_post(); the_post_thumbnail('thumbnail'); //lists thumbnails the_title(); // shows titles the_permalink(); //link to the current page wp_reset_postdata(); //remember to reset data
NB! Remember to set thumbnails in the page’s “Set featured image” window!
We’ve styled the list right in the function, but you can use it with CSS as well. Here is how our function looks like:
function my_function() { global $post; $child_pages_query_args = array( 'post_type' => 'page', 'post_parent' => $post->ID, 'orderby' => 'date DESC' ); $child_pages = new WP_Query( $child_pages_query_args ); if ( $child_pages->have_posts() ) : ?> <ul class="child_page_row"> <?php while ( $child_pages->have_posts() ) : $child_pages->the_post(); ?> <li><a href="<?php the_permalink(); ?>"> <?php if(has_post_thumbnail()): ?> <div class="child_page_thumb"> <?php the_post_thumbnail(array(240, 240)); ?> </div> <?php endif; ?> <div class="child_page_name"> <?php the_title(); ?> </div> <?php if(has_post_custom_meta('Desc')) : ?> <div class="child_page_desc"> <?php echo get_post_meta($post->ID, 'Desc', true); ?> </div> <?php endif; ?> <div class="child_page_author"> <a href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ) ); ?>">@ <?php the_author(); ?></a> </div> </a></li> <?php endwhile; ?> </ul> <?php endif; wp_reset_postdata(); }
Here is a basic CSS code for this example that will make it look like in the “tutorials” example:
ul.child_page_row { list-style: none; } ul.child_page_row li { display: inline-block; margin: 0 0 20px 20px; border: 1px solid rgba(127,127,127,.1); } ul.child_page_row li a { text-decoration: none; } ul.child_page_row li .child_page_thumb { height: 240px; } ul.child_page_row li .child_page_name { margin: 15px; font-weight: 700; color: #000; font-size: .9em; }
Listing Child Pages directly will print them at the top of your page. If you want to show your pages in the middle of the post or at the end, you will need to return the resulting HTML from the function.
In order to return HTML you will need to create HTML code inside the function and store it in a temporary variable $result
before returning at the end.
Here’s a simple code how to get and return Child Pages from a function:
$args = array( 'post_type' => 'page', 'post_status' => 'publish', 'parent' => $parent, 'hierarchical' => 0 ); $children = get_pages($args); $result = "<ul>"; foreach ( $children as $child ) { $child_id = $child->ID; $url = get_permalink( $child_id ); $thumb = get_the_post_thumbnail($child_id, array(240, 240)); $title= $child->post_title; $link = "<a href='$url'><div class='child_page_thumb'>$thumb</div><div class='child_page_title'>$title</div></a>"; $result .= "<li>$link</li>"; } $result .= "</ul>"; return $result;
Easiest way to call the function from the parent page is to make a shortcode:
add_shortcode('show_child_pages', 'my_function');
Then the parent page would have just one line of code that will list all it’s child pages like you want:
[show_child_pages]
And the result: Tutorials
In some cases we would like to list the parent along with child pages. In this case we need to add the parent page to our list.
In our example we will be showing the top-level page along with all its child pages styled with the same CSS. We won’t be duplicating any code specially for the parent page, but move the repeatable chunk into its own function list_page
:
function list_page() { ?> <li><a href="<?php the_permalink(); ?>"> <?php if(has_post_thumbnail()): ?> <div class="child_page_thumb"> <?php the_post_thumbnail(array(240, 240)); ?> </div> <?php endif; ?> <div class="child_page_name"> <?php the_title(); ?> </div> <?php if(has_post_custom_meta('Desc')) : ?> <div class="child_page_desc"> <?php echo get_post_meta($post->ID, 'Desc', true); ?> </div> <?php endif; ?> <div class="child_page_author"> <a href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ) ); ?>">@ <?php the_author(); ?></a> </div> </a></li> <?php }
Now, we will call this function from the loop as before:
while ( $child_pages->have_posts() ) : $child_pages->the_post(); list_page(); endwhile;
To add a top-level page or parent page we will need to get it first:
$parent_page = get_page($post->ID);
Now, call our new function list_page()
.
That’s it!
Here is the new version of the code with a parent page:
function my_function() { global $post; $child_pages_query_args = array( 'post_type' => 'page', 'post_parent' => $post->ID, 'orderby' => 'date DESC' ); $child_pages = new WP_Query( $child_pages_query_args ); if ( $child_pages->have_posts() ) : ?> <ul class="child_page_row"> <?php $parent_page = get_page($post->ID); list_page(); while ( $child_pages->have_posts() ) : $child_pages->the_post(); list_page(); endwhile; ?> </ul> <?php endif; wp_reset_postdata(); } function list_page() { ?> <li><a href="<?php the_permalink(); ?>"> <?php if(has_post_thumbnail()): ?> <div class="child_page_thumb"> <?php the_post_thumbnail(array(240, 240)); ?> </div> <?php endif; ?> <div class="child_page_name"> <?php the_title(); ?> </div> <?php if(has_post_custom_meta('Desc')) : ?> <div class="child_page_desc"> <?php echo get_post_meta($post->ID, 'Desc', true); ?> </div> <?php endif; ?> <div class="child_page_author"> <a href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ) ); ?>">@ <?php the_author(); ?></a> </div> </a></li> <?php }
In order to list grandchild pages we need to use a recursive function where we get children for one level at a time. Another approach is a bit easier. We are going to use a WordPress function get_pages
to get all children and grandchildren at once.
args
of the query and use child_of
parameter:
$child_pages_query_args = array( 'post_type' => 'page', 'child_of' => $post->ID, 'orderby' => 'date DESC' ); $child_pages = get_pages( $child_pages_query_args );
function list_page($page) { ?> <li><a href="<?php echo get_permalink($page->ID); ?>"> <?php if(has_post_thumbnail($page->ID)): ?> <div class="child_page_thumb"> <?php echo get_the_post_thumbnail($page->ID, array(240, 240)); ?> </div> <?php endif; ?> <div class="child_page_name"> <?php echo get_the_title($page->ID); ?> </div> </a></li> <?php }
foreach($child_pages as $page) { list_page($page); }
Here is the latest version of the code with parent page and all children and grandchildren:
function my_function() { global $post; $child_pages_query_args = array( 'post_type' => 'page', 'child_of' => $post->ID, 'orderby' => 'date DESC' ); $child_pages = get_pages( $child_pages_query_args ); if ( $child_pages) : ?> <ul class="child_page_row"> <?php $parent_page = get_page($post->ID); list_page($parent_page); foreach($child_pages as $page) { list_page($page); } ?> </ul> <?php endif; wp_reset_postdata(); } function list_page($page) { ?> <li><a href="<?php echo get_permalink($page->ID); ?>"> <?php if(has_post_thumbnail($page->ID)): ?> <div class="child_page_thumb"> <?php echo get_the_post_thumbnail($page->ID, array(240, 240)); ?> </div> <?php endif; ?> <div class="child_page_name"> <?php echo get_the_title($page->ID); ?> </div> </a></li> <?php } add_shortcode('show_child_pages_custom', 'my_function');
If your site crashes while trying some of the code samples above, then it’s probably some kind of PHP error. You need to take a look at your PHP error log file. Check out debugging options in WP.
Senior Software Engineer developing all kinds of stuff.
*
Is it possible to list the parent site of these childs to in the list?
Hi,
yes, I have updated the post. Please, see section 2.
Hi,
I have followed the tutorial above and everything is working fine but my output is displayed at the top of the page instead of been displayed after the content where i have added the shortcode.
A cause to this problem is using echo to output the code from the shortcode. If you need to wrap the output in some content, you need to return a string containing the output in order for it to appear in the correct spot.
Edit: I have updated the post and section 2 now shows how to return the code from the function.
Great work – What if you wanted to list the grandchild pages as well?
Hello, you may use the function get_pages. I have updated the post with a code example, see section 3.
How to display only child pages of the first level. I tried to insert in the function value $depth=1, but it’s not working
Hello,
not sure I understand the problem. The first section of the article “List child pages” shows how to list only child pages of the first level. Where did you try to insert depth? Which code example?
I tried pasting code taken from here, but get a 500 error. The latest version of the code is displayed correctly, but with child pages of all levels
What is the structure of your child pages?
Example:
parent
-child
-child
—-child
—-child
-child
I need to leave only the first level
When you visit one of the 2 child pages – what URL do you see? I’m using this code on my tutorials page with the same structure as yours and it works.
First level children: https://sftextures.com/tutorials
Second level children: https://sftextures.com/tutorials/graphic-design-tutorials/
Could you send your code from functions.php to my mail. I tried to insert the function code on different sites, but everywhere the result is HTTP ERROR 500. Sorry for bothering
Hello. List child pages code doesn’t work. I always have HTTP ERROR 500.
I just have copy/paste your code. I can’t find where is the problem 🙁 Please could you help me ?
sorry for previous post. Then the code which give me ERROR 500.
global $post;
$child_pages_query_args = array(
'post_type' => 'page',
'post_parent' => $post->ID,
'orderby' => 'date DESC'
);
$child_pages = new WP_Query( $child_pages_query_args );
while ( $child_pages->have_posts() ) : $child_pages->the_post();
the_post_thumbnail('thumbnail'); //lists thumbnails
the_title(); // shows titles
the_permalink(); //link to the current page
wp_reset_postdata(); //remember to reset data
function my_function() {
global $post;
$child_pages_query_args = array(
'post_type' => 'page',
'post_parent' => $post->ID,
'orderby' => 'date DESC'
);
$child_pages = new WP_Query( $child_pages_query_args );
if ( $child_pages->have_posts() ) :
?>
have_posts() ) : $child_pages->the_post();
?>
<a href="">
ID, 'Desc', true); ?>
<a href="">@
<?php
endif;
wp_reset_postdata();
<?php
}
add_shortcode('show_child_pages', 'my_function');
Hello,
the reason it doesn’t work for you is that you have copied and pasted all the code from my post. You shouldn’t do it as parts 1.1-1.4 are just explanations. Please remove 1.1 and 1.2 and use only part 1.3 and 1.4 in your PHP file – it will at least fix the 500 error.
Hello,
I use the latest version you have added at the end of the article. It works, but it doesn’t look the same as your example. Do you know how that is possible?
Please, provide more details. I can’t see what example you are referring to. I have provided a link to the example for the code in part 1, 2 and 3. The code at the end of the article lists all child pages including grandchildren.
Well in the example of “tutorials” i see all childpages nicely lined up next to each other.
I have tried the code under 1.3 style the list, but when i add that code to my functions.php my site chrashes.
1. In order to make childpages look like in the example you need to use the same CSS code. I have updated the article with a basic CSS for this example.
2. Thanks for pointing it out. There really was a little bug in that code. It’s now fixed.
I am trying to get the code for Return Child Pages section to work. I have entered the following in the functions.php:
and then entered the following in my page template for the custom post type (which is hierarchical):
Nothing is shows up on my page even though is has 16 child pages.
It didn’t show my 2nd code because I forgot to remove the php tags. This is what I put in my template file:
Hello, use “echo” in your page template. It will print the resulting pages.