WordPress: How to style wp_list_pages
Posted on: 09.25.08Applying styling to dynamically generated lists (or any content) in WordPress.
Recently, I was in a need of changing the default outcome of the <?php wp_list_pages(‘arguments’); ?> tag in WordPress – as you’ll see, it’s a really simple procedure. I needed to change the wp_list_pages outcome, but this technique can be applied to other tags as well.
On default, after calling this script, we recieve something along these lines:
<ul>
<li class="page_item current_page_parent">
<a href="#">Link</a>
</li>
<li class="page_item">
<a href="#">Link2</a>
</li>
</ul>
On some ocasions you will probably wish to add a <class> or a <span> to each link. Too bad that the wp_list_pages() tag doesn’t take as arguments strings to go before and after each link.
So, this is the way that you can go around this problem:
- Find your wp_list_pages() tag in the template
- Change the <?php wp_list_pages(‘arguments’); ?> into the following:
1 2 3 4 5 6 7 8 9 10 | <?php $my_pages = wp_list_pages('echo=0&title_li='); $var1 = '<a'; $var2 = '<span class="testClass"><a'; $var3 = '</a'; $var4 = '</a></span>;'; $my_pages = str_replace($var1, $var2, $my_pages); $my_pages = str_replace($var3, $var4, $my_pages); echo $my_pages; ?> |
- The above looks for strings $var1 and $var3 and changes them with $var2 and $var4, respectively in the $my_pages variable (which is the outcome of the wp_list_pages() tag)
- It is important to pass echo=0&title_li= as arguments because the output would be otherwise not stored as the &my_pages variable (echo=0) and the list would have a title – typically “Pages” (title_li=)
- After this operation the previous code looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 | <ul>
<li class="page_item current_page_parent">
<span class="testClass">
<a href="#">Link</a>
</span>
</li>
<li class="page_item">
<span class="testClass">
<a href="#">Link2</a>
</span>
</li>
</ul> |
And this is it! Simple yet powerful. This litlle trick can have many applications (like, for example, creating a hover effect with some script on the menu) and it is up to you what to do with it next. If you are going to use it for something – it’s always appreciated if you could share your ideas.
Update! I’ve noticed that a lot of interest is paid to this post. If some of you would like me to explain something in more detail, then ask for it in a comment. I hope that I will be able to help :)
Update 2! I have written a new post about modifying the outcome of the wp_list_pages tag – have a look here: WordPress: how to dynamically modify the output of the wp_list_pages tag
Take care!
Maciek
Q1: How would one style an element inside a link?
Here is a little modification of the script to include styling of parts of a link, as suggested by Ben, although Ben’s problem was a little more complex.
The problem is how to style one part of a link, for example: The link is “WordPress Rocks!” and we want to apply style only to the word “WordPress”, to be… mmmm…. bold and green! That’s how to do it:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php $my_pages = wp_list_pages('echo=0&title_li='); $var1 = '<a'; $var2 = '<span class="testClass"><a'; $var3 = '</a'; $var4 = '</a></span>;'; $var5 = 'Wordpress'; $var6 = '<h10>Wordpress</h10>'; $my_pages = str_replace($var1, $var2, $my_pages); $my_pages = str_replace($var3, $var4, $my_pages); $my_pages = str_replace($var5, $var6, $my_pages); echo $my_pages; ?> |
As you can see, I have wrapped the word “WordPress” in <h10> tag. Why not <span>? Because for what I know it creates a bunch of gibberish as outcome (try it and you’ll know it). <h10>, or any <h> tag which is not being used, is a simpler solution.
Don’t forget to style it in your CSS file. If the <h> tag breaks your line, use “display:inline;” in your style sheet to fix it.
h10 { font-weight: bold; color: Green; display: inline; }
Oh, and I am assuming that the word “WordPress” is a constant output from the wp_list_pages(). This means, that wp_list_pages() always outputs the word “WordPress”.
Q1: How to add a line between to <li> elements?
Here’s how:
1 2 3 4 5 6 7 | <?php $my_pages = wp_list_pages('echo=0&title_li='); $var1 = '/li><li'; $var2 = '/li> whatever you want to add here <li'; $my_pages = str_replace($var1, $var2, $my_pages); echo $my_pages; ?> |
UPDATED!!! 25.04.2009
Q2: How do you create a dynamic submenu?
Marc Wiest was kind to share wit us a solution to this problem, based on the above hack and work by Gabriel Svennerberg.
Here is how to create a dynamic submenu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php $has_subpages = false; // Check to see if the current page has any subpages $children = wp_list_pages('&child_of='.$post->ID.'&echo=0'); if($children) { $has_subpages = true; } // Reseting $children $children = ""; // Fetching the right thing depending on if we're on a subpage or on a parent page (that has subpages) if(is_page() && $post->post_parent) { // This is a subpage $children = wp_list_pages("title_li=&include=".$post->post_parent ."&echo=0"); $children .= wp_list_pages("title_li=&child_of=".$post->post_parent ."&echo=0"); } else if($has_subpages) { // This is a parent page that have subpages $children = wp_list_pages("title_li=&include=".$post->ID ."&echo=0"); $children .= wp_list_pages("title_li=&child_of=".$post->ID ."&echo=0"); } ?> <!--Check to see if we have anything to output--> <?php if ($children) { ?> <div class="subNav"> <ul> <li> <!--modified wp_list_pages--> <?php $var1 = '<a'; $var2 = '<span class="testClass"><a'; $var3 = '</a>'; $var4 = '</a></span>'; $children = str_replace($var1, $var2, $children); $children = str_replace($var3, $var4, $children); echo $children; ?> <!--end of modified wp_list_pages--> </li> </ul> </div><!--subNav--> <?php } ?> |
I didn’t get a chance to test out this code (but it looks alright to me and it works for Marc), so if you run into any problems, let me know in the comment.
Also you are welcome to share your problems and solutions.
Again, thanks Marc!
If you found this post interesting, have a look at the one about dynamically modifying the wp_list_pages output
Comments (30)
Ben added these words on Feb 04 09 at 06:19What if I have a link to a page with two words and I want to assign a class to only 1 word? For example, the page name is “magic tricks” and I want to apply some CSS styling only to the word “magic” but not the word trick. Yet, with wp_list_pages they will be sent from WordPress as 1 item. This is pretty tricky and I haven’t had any luck yet with getting it to work. Any ideas?
Ben added these words on Feb 04 09 at 06:21In my above comment, I wanted the to look like code, but I think I did it wrong. Can you edit it? Sorry. Thanks!
rocksea added these words on Feb 23 09 at 11:55great tip on styling the wp_list_pages function! thanks a lot :)
RaiulBaztepo added these words on Mar 30 09 at 11:25Hello!
Very Interesting post! Thank you for such interesting resource!
PS: Sorry for my bad english, I’v just started to learn this language ;)
See you!
Your, Raiul Baztepo
marc added these words on Apr 24 09 at 15:10wassup,
nice post! i wandering though! how do i hack the children in the same way? (my children a separate from the the wp_list_pages tag) thanks!
marc
marc added these words on Apr 24 09 at 16:06hey dude,
i found a nice solution for my question above. i’d like to post it here but wp would eat up the code snippet i have worked it out with the help of this tutorial (code snippet) http://tiny.cc/svennerberg. contact me if you are interested.
greetz marc
Rick added these words on Apr 26 09 at 10:45I want to have a selected parent page not link to anything but the children in the drop down actually be links (no anchor text). I have seen a lot of people asking for this but have not found any answers even after extensive searching.
Someone has said that it can’t be done with wp_list_pages(). You need to use get_pages instead. Either way, this is beyond my abilities. Any suggestions? Thanks.
Maciej Wantusiak added these words on Apr 26 09 at 11:57I’m away for couple of days, but I’ll look into it when I’m back… In the mean time maybe someone else will have a solution?
Rick added these words on Apr 26 09 at 12:15Clarification of my request: I am trying to have a selected parent page in the menu not link to its page so that the user has to select one of the child pages in the drop down menu for that item.
marc added these words on Apr 28 09 at 10:38@rick,
i don’t quite understand your question. but if your question is about the submenu update from the 25th of april, it would be best to look for help at http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/comment-page-1/#comment-3602 that’s where i got the submenu snippet from. i don’t know much about php, so i can’t help you. i just got lucky playing around with these two snippets. good luck.
Jessicajelo added these words on May 10 09 at 17:40I love it! That is way cool man! The steps weren’t that complicated too, which is great.
ArianaVent added these words on May 13 09 at 12:39Great! Thank you very much! I always wanted to write in my blog something like that. Can I take part of your post to my site? Of course, I will add backlink? Regards
Muham added these words on Aug 14 09 at 14:52Part2 doesn’t work. It doesn’t give you a completely serparated menu/submenu. The menu only shows the parent of the submenu when either the parent is selected or the child is selected. Horribly broken code it is.
You need to show the main nav 100% of the time and the children only if they exist. Then when a child is selected, both menu need to still appear (not disappear).
Maciej Wantusiak added these words on Aug 14 09 at 18:53Muham,
Thanks for sharing this with us. I won’t get a chance to check this code and try to find a solution for at least a week, so in the mean time, if you find an answer, would you mind sharing it with others?
Cheers!
zezinozen added these words on Sep 16 09 at 21:28Hello,
Thanks very much for this tut!.. a nooby question.. how can I output the list in two columns, I have 56 pages and it is a lot of scroll.. I would like to limit and then go to another column.. any help really appreciate and please I am learning :)
Maciej Wantusiak added these words on Sep 17 09 at 12:52Hmmm… Depending on how you want to divide the list (in half, or after a certain number of positions) I would try to write a script that divides the output of wp_list_pages into an array (split at every < li > ), so you know instantly the amount of the entries, and output them one by one, inserting a closure of the first column and opening of the second one after a certain number of outputs.
Check out my other post on this subject: http://www.wantusiak.com/wordpress/wordpress-modify-wp_list_pages – there I describe how to divide an output into an array
Marcy Sutton added these words on Sep 29 09 at 23:18The first example for re-outputting wp_list_pages(‘args’) does not affect my sidebar at all. I tried it first with my code, and then yours — and it has no effect on the Pages child . I am putting it in sidebar.php, do not have a dynamic sidebar enabled, so it should work but doesn’t. I am running WordPress 2.8.4.
$my_pages = wp_list_pages('title_li=Pages');
$var1 = '<a';
$var2 = '» <a';
$my_pages = str_replace($var1, $var2, $my_pages);
JohnnyPea added these words on Oct 27 09 at 09:33When I am using:
whatever you want to add here
How can I avoid it between the subpages?
Maciej Wantusiak added these words on Oct 27 09 at 12:24Hi Johnny,
Can you clarify what exactly do you want to avoid between the subpages?
Thanks
Edward Rpss added these words on Feb 08 10 at 18:02Useful post – worth noting that since WordPress 2.7 there are parameters to the wp_list_pages to do this:
link_before and link_after
Maciek added these words on Feb 08 10 at 20:49Thanks!
At least it was worth something for some time :)
cposada added these words on Apr 02 10 at 18:09Thank you for this write up. I used its methods to change the markup for a site I was working on. Unfortunately, the link_before and link_after do not work for my needs. I needed to change the markup within the anchor tag itself. I was then able to use the code at http://www.cssplay.co.uk/menus/snazzymenu.html in order to create rounded corners without images. I still need to tidy up my code a bit but it works flawlessly. Thank you for the direction you turned me to.
Maciek added these words on Apr 03 10 at 20:02I am glad that I could be helpful! :)
Good luck with your design!
All the best,
Maciek
Ronny added these words on Apr 03 10 at 23:40Thanks man! That just saved me. :-)
Abid Ali added these words on Apr 12 10 at 08:59how to mix pages and categories in the menu.