Reputation: 15434
I'm new to WordPress and want to create a menu. With wp_list_pages()
I can generate a list of links wrapped in <li>
tags.
This is fine, but I want to add my own classes to these (and also perhaps change the elements wrapping them).
I've looked through https://developer.wordpress.org/reference/functions/wp_list_pages/ and a few forum posts but have not been able to find anything the points me in the right direction.
How can I customise the output of wp_list_pages?
Upvotes: 2
Views: 2000
Reputation: 809
I found two ways,
Using filters and regular expressions
Add following to your theme functions.php
file.
function clean_wp_list_pages($menu) {
// Remove redundant title attributes
$menu = remove_title_attributes($menu);
// Remove protocol and domain name from href values
$menu = make_href_root_relative($menu);
// Give the list items containing the current item or one of its ancestors a class name
$menu = preg_replace('/class="(.*?)current_page(.*?)"/','class="sel"',$menu);
// Remove all other class names
$menu = preg_replace('/ class=(["\'])(?!sel).*?\1/','',$menu);
// Give the current link and the links to its ancestors a class name and wrap their content in a strong element
$menu = preg_replace('/class="sel"><a(.*?)>(.*?)<\/a>/','class="sel"><a$1 class="sel"><strong>$2</strong></a>',$menu);
return $menu;
}
add_filter( 'wp_list_pages', 'clean_wp_list_pages' );
Using a custom walker function
It is the same as above. Add this to your functions.php file:
class Clean_Walker extends Walker_Page {
function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul>\n";
}
function start_el(&$output, $page, $depth, $args, $current_page) {
if ( $depth )
$indent = str_repeat("\t", $depth);
else
$indent = '';
extract($args, EXTR_SKIP);
$class_attr = '';
if ( !empty($current_page) ) {
$_current_page = get_page( $current_page );
if ( (isset($_current_page->ancestors) && in_array($page->ID, (array) $_current_page->ancestors)) || ( $page->ID == $current_page ) || ( $_current_page && $page->ID == $_current_page->post_parent ) ) {
$class_attr = 'sel';
}
} elseif ( (is_single() || is_archive()) && ($page->ID == get_option('page_for_posts')) ) {
$class_attr = 'sel';
}
if ( $class_attr != '' ) {
$class_attr = ' class="' . $class_attr . '"';
$link_before .= '<strong>';
$link_after = '</strong>' . $link_after;
}
$output .= $indent . '<li' . $class_attr . '><a href="' . make_href_root_relative(get_page_link($page->ID)) . '"' . $class_attr . '>' . $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . '</a>';
if ( !empty($show_date) ) {
if ( 'modified' == $show_date )
$time = $page->post_modified;
else
$time = $page->post_date;
$output .= " " . mysql2date($date_format, $time);
}
}
}
To use this you need to call wp_list_pages with a walker parameter.
<?php
$walker = new Clean_Walker();
wp_list_pages( array(
'title_li' => '',
'walker' => $walker,
) );
?>
Source: here
Upvotes: 1
Reputation: 115
You would be able to achieve this by overriding the .page-item class. Check here for more details https://developer.wordpress.org/reference/functions/wp_list_pages/#more-information
If you need to add custom classes or change the way the list is rendered you can attach a walker function https://developer.wordpress.org/reference/classes/walker/
An example can be found at https://developer.wordpress.org/reference/classes/walker_nav_menu/
class Custom_Walker_Page extends Walker_page {
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{
//You can make your change here
}
}
$args = array(
.....
.....
'walker' => new Custom_Walker_page()
Upvotes: 0