When reading posts it is common to see links to the next and previous post in the sequence. Something like this:
It’s a nice feature that keeps readers engaged in your content and also aids accessibility by improving navigation. Recently, though, I worked on a project that required adding page (not post) links after the content area on pages that had the same parent (i.e., page siblings). So, something like this:
Instead of manually adding the links, I wrote a little helper function to do the job for me. Here’s how I did it.
<?php | |
/** | |
* Calls the page link functions on pages that are descendants of $greatest_ancestor | |
* | |
* @param int $greatest_ancestor The ID of the top level ancestor | |
*/ | |
function tj_page_navigation_links( $greatest_ancestor ) { | |
//* Get the ancestors of the current page | |
$page_ancestors = get_post_ancestors( get_the_ID() ); | |
//* Return early if not a descendant of $page_ancestors | |
if ( ! in_array( $greatest_ancestor, $page_ancestors) ) | |
return; | |
$args = array( | |
'post_parent' => $page_ancestors[0], | |
'post_status' => 'publish', | |
'orderby' => 'menu_order', | |
'order' => 'ASC', | |
); | |
$siblings = array_keys( get_children( $args ) ); | |
$position = array_search( get_the_ID(), $siblings ); | |
tj_prev_sibling_link( $siblings, $position ); | |
tj_next_sibling_link( $siblings, $position ); | |
} | |
/** | |
* Renders the Prev: Page button | |
* | |
* @param array $siblings All children of $greatest_ancestor | |
* @param int $position Position of the current page among its siblings | |
*/ | |
function tj_prev_sibling_link( $siblings, $position ) { | |
if ( get_the_ID() == $siblings[0] ) | |
return; | |
//* Render a button that links to the previous sibling page. | |
$prev_sibling_permalink = get_the_permalink( $siblings[$position-1] ); | |
$prev_sibling_title = get_the_title( $siblings[$position-1] ); | |
printf( '<a class="%s" href="%s">%s</a>', 'button prev', $prev_sibling_permalink, 'Prev: ' . $prev_sibling_title ); | |
} | |
/** | |
* Renders the Next: Page button | |
* | |
* @param array $siblings All children of $greatest_ancestor | |
* @param int $position Position of the current page among its siblings | |
*/ | |
function tj_next_sibling_link( $siblings, $position ) { | |
if ( get_the_ID() == end( $siblings) ) | |
return; | |
//* Render a button that links to the next sibling page. | |
$next_sibling_permalink = get_the_permalink( $siblings[$position+1] ); | |
$next_sibling_title = get_the_title( $siblings[$position+1] ); | |
printf( '<a class="%s" href="%s">%s</a>', 'button next', $next_sibling_permalink, 'Next: ' . $next_sibling_title ); | |
} |
What we are doing here is first checking if the current page is a child of $greatest_ancestor
, which is simply the ID of the ancestor page (e.g., parent, great-grandparent, etc.) in question. If so, then we retrieve a list of the current page’s siblings according to 'menu_order'
and check where we are in the sequence. Finally, we render the buttons for the previous and next pages in the sequence, if they exist.
To use the above code, simply call it like this:
<?php | |
add_action( 'genesis_entry_footer', 'tj_subpage_navigation' ); | |
/** | |
* Adds page links to the descendants of page ID 6. | |
* | |
*/ | |
function tj_subpage_navigation() { | |
//* Return early if not on a page or if on the front page | |
if ( ! is_page() || is_front_page() ) | |
return; | |
$greatest_ancestor = 6; // Change this number to the ID of your parent/grandparent page | |
tj_page_navigation_links( $greatest_ancestor ); | |
} |
Mind you, I am using a Genesis hook here. If you are not using Genesis, then you will need to find your theme framework’s appropriate hook (if one exists), or insert tj_page_navigation_links( $greatest_ancestor );
directly into the desired location within your child theme.
Because the siblings are ordered by 'menu_order'
you can conveniently arrange the sequence by changing the “Order” value under Page Attributes, or by using a plugin like Simple Page Ordering.
Leave a Reply