This sliding doors CSS hack allows you to create sophisticated tabs for your navigation bar. Sadly, WordPress core functions wp_list_pages() and wp_list_categories() don’t allow you to add the required span tag to use this technique.
We are going to see how to proceed in order to use sliding doors in our WordPress theme.
Sliding doors, why?
There’s many articles available on the web about the sliding doors technique, so I’m not going to talk a lot about it. For people who don’t already know this famous hack, here’s a quick example.
Let’s build a typical navigation list:
<ul id="nav">
<li><a href="#">link n°1</a></li>
<li><a href="#">link n°2</a></li>
<li><a href="#">link n°3</a></li>
</ul>
If we apply, via CSS, background images to our links in order to make this menu prettier, we’ll quickly see a big problem: We must add a fixed width to the links, otherwise the image will be truncated if the link is too short, or the link will overflow the image if its width is too long.
That’s why sliding doors are very useful: We just have to add a span element inside the link, and then, in our CSS, assign a different background image to both the span element and the link.
<ul id="nav">
<li><a href="#"><span>link n°1</span></a></li>
<li><a href="#"><span>link n°2</span></a></li>
<li><a href="#"><span>link n°3</span></a></li>
</ul>
Our CSS should look like this:
#nav a, #nav a:visited {
display:block;
}
#nav a:hover, #nav a:active {
background:url(images/tab-right.jpg) no-repeat 100% 1px;
float:left;
}
#nav a span {
float:left;
display:block;
}
#nav a:hover span {
float:left;
display:block;
background: url(images/tab-left.jpg) no-repeat 0 1px;
}
Please note, as this is only an example, the CSS above isn’t complete and only shows how to apply the sliding doors hack.
You can see a live demo of a navigation menu which uses this technique on my blog here.

Using the sliding doors hack within WordPress
I saw many blog posts where some users told you to modify WordPress core in order to apply this technique. Personally, I never really liked this idea: First, the WordPress core wasn’t made for being modified. And secondly, if you do, when you’ll upgrade your WP version, you’ll have to re-modify the core. Not user friendly at all!
Instead of this, let’s use a regular expression, by using the php preg_replace() function. We are going to get our pages (or categories) without displaying it, and passing it as a parameter to preg_replace(). The two remaining parameters will be, of course, our regular expression: The pattern we’re looking for, and this pattern’s replacement.
To create this menu, paste the following code instead of the wp_list_pages() (or wp_list_categories()) function in the header.php of your WordPress theme.
To list your pages:
<ul id="nav">
<li><a href="<?php echo get_option('home'); ?>/"><span>Home</span></a></li>
<?php echo preg_replace('@\<li([^>]*)>\<a([^>]*)>(.*?)\<\/a>@i', '<li$1><a$2><span>$3</span></a>', wp_list_pages('echo=0&orderby=name&exclude=181&title_li=&depth=1')); ?>
</ul>
To list your categories:
<ul id="nav">
<li><a href="<?php echo get_option('home'); ?>/"><span>Home</span></a></li>
<?php echo preg_replace('@\<li([^>]*)>\<a([^>]*)>(.*?)\<\/a>@i', '<li$1><a$2><span>$3</span></a>', wp_list_categories('echo=0&orderby=name&exclude=181&title_li=&depth=1')); ?>
</ul>
Right now, your new menu is ready. You just have to make it sexy with CSS. Have fun!
















thats it.. thanx.. been figure it out forever..
You’re welcome
Very nice code I’m impressed Jean-Baptiste.
Thanks a lot, Hayes!
Sorry, I just get these errors with wordpress 2.5.1:
“Parse error: parse error, unexpected ‘)’, expecting ‘,’ or ‘;’”
I got it – just a silly thing: Your (or this blog) wrote “?” instead of “‘”. So now, everything is fine. thanks for your code.
@Ben: Glad you fixed your problem. Can you tell me where the “?” is? I need to correct that mistake asap so no-one will have this problem again.
Sorry, it seems that the blog reformated the character. Some of the ‘ characters are italic for me – I replaced them with the original ‘ and it works for me.
best regards
ben
Oh, ok. It’s a well known problem.
As Kyle said in another post, when you copy code from a blog, ALWAYS paste it on a plain text editor (Vi, emacs, Microsoft Notepad, TextEdit…) and then copy the code from the editor.
I work with TYPO3, so I usually do that
But also in Editor they are different characters (maybe it works this time): ’ (italic) and ‘ (like it should be).
Haha, when I cop now my entry before into the editor, the regular character is wrong also. Maybe also a problem with the font or something like that. But thanks for your help and the good code.
Fantastic tutorial! I’ll make sure to blog about this later on.
Thanks a lot Patrick, I’m glad you liked the tutorial
Great trick there , thanks alot!
Quick q from a newbie…we’re using Joomla for a site we’re building and want to use the sliding door technique for our front page…
Does your CSS hack work if we’re not using wordpress?
Thanks in advance.
Steve & Irv
For sure, there’s a way to do the same thing in Joomla but I never tried. You should keep the regular expressions, and try if it works once adpted to Joomla.
I’ll be curious to know, so don’t hesitate to come back here and tell us about your experience!
Hi………..
Oh! nice article. Please visit and enjoyed this article.
Thank you
CSS
Hy, i’m having a problem copying and pasting the code,
Well i’m not dumb, but the code gives me a parse error when trying to execute the page…
Can someone email me the code ? valerio.jezus@gmail.com thanks in advance.
@Valerio: I think the problem is the quotes. You should replace them manually, and everything will works
Thanks for the code! I needed it for both top level and sub nav and modified it a bit. Here’s the code for listing the sub-level page navigation:
post_parent)
$children = wp_list_pages(“title_li=&child_of=”.$post->post_parent.”&echo=0″);
else
$children = wp_list_pages(“title_li=&child_of=”.$post->ID.”&echo=0″);
if ($children) { ?>
<?php echo preg_replace(‘@\]*)>\]*)>(.*?)\@i’, ‘$3‘, $children); ?>
I just wanted to thank you for a great tutorial, it really helped me in writing a tutorial on how to implement menus genereted by my site in WordPress, though I must say that I think the WordPress team should have a look at their wp_list_pages function and start allowing people to add custom class names to the ul tag, li tag and a tag and the option to add a span tag inside. Good and good looking navigation is pretty important and if it wasn’t for guys like you, writing these tutorials, most people would have a hell of a time figuring out how to do this.
Anyway once again, thank you for a great tutorial, you saved me a lot of time and I made sure to make a point of all the credit, for this technique, going this way.
So fun with it
So nice .. Thnx
You shouldn’t need this “hack” with the new 2.7 version of WordPress, “we” got them to implement the same parameters as the wp_link_pages link_before / link_after.
“link_before and link_after for wp_list_pages()”
http://trac.wordpress.org/changeset/9484
http://trac.wordpress.org/ticket/8041
Next should be for categories..
http://codex.wordpress.org/index.php?title=Template_Tags%2Fwp_link_pages&diff=62692&oldid=46067
@spencerp: Good to know! But this hack was very useful to me until WP 2.7.
just what the doctor ordered…
thumbs up
This steers me in the direction I was seeking – thank you. However, I’d like to swap the background image for the currently selected page using CSS. If it’s possible, where in the code might I insert a class=”current” id?
I about cried when I saw this post, since I have been trying to figure this out for days. Very excited.
Then I put the code in after copying it from another text editor to remove syntax error, and I get the following:
Warning: Unexpected character in input: ”’ (ASCII=39) state=1 in /home/zacharyr/public_html/sandbox/wp-content/themes/clean-copy-right-sidebar-1/header.php on line 34
Warning: Unexpected character in input: ‘\’ (ASCII=92) state=1 in /home/zacharyr/public_html/sandbox/wp-content/themes/clean-copy-right-sidebar-1/header.php on line 34
Parse error: syntax error, unexpected ‘<’ in /home/zacharyr/public_html/sandbox/wp-content/themes/clean-copy-right-sidebar-1/header.php on line 34
I know you are busy but any help would be greatly appreciated.
I previously posted about this wasn’t working, but that is because of the syntax with the ‘ and ” so future people please watch out.
If there is a God, I hope he (or she) sends you directly into heaven and hands over your 40 virgins for this WP hack.
@zach: It’s due to the curly quotes. Just manually replace it and you’re done!
Read more about it here.
I need vertical css menu
Thanks! Just what I needed.
Question:
If we are using the A List Apart CSS Sliding doors technique, they use an id=”current” in the li tag to create the active tab. How can I make it so that you code will append the id=”current” to the li tag of the active category?
Thanks for the help, this is a great tutorial!
Thankyou! I nearly cried when I saw this. I have been looking for a way to add spans for ages!
Since WordPress 2.7 you don’t need to do this anymore, use wp_list_pages parametes link_before and link_after:
wp_list_pages(
array(
‘link_before’=>”,
‘link_after’=>”
)
);
(need wordpress 2.7+)
it’s in the docs here:
http://codex.wordpress.org/Template_Tags/wp_list_pages
OMG! If ever there was a true WordPress God, it is you! Thank you soooo much for this. Now I knew there was something silly going on, but I just couldn’t figure it out. I have been trying to wrap my brain around this problem for the last 4 hours. Suddenly I find this post and realized the solution was at my finger tips the entire time. I am running version 2.8 so this hack is not necessary anymore, but it led me to the place on the WordPress site which told me how to do it with version 2.8 http://codex.wordpress.org/Template_Tags/wp_list_pages
<?php wp_list_pages(‘orderby=name&exlude=2&title_li=&depth=1&link_before=&link_after=’); ?>
Thanks again guys!
Just one question. I have this code in a wordpress theme. Now, if I want to exclude certain pages to show up, how do I do that?
Leslie
You can use “Exclude”:
Use the exclude parameter to hide certain Pages from the list to be generated by wp_list_pages.
Oh my God – I too cried when I found this. Thank you so much.
What an incredibly useful article!
I wound up using it like this in header.php and it worked perfectly with wp_page_menu:
<?php echo preg_replace('@\]*)>\]*)>(.*?)\@i’, ‘$3‘, wp_page_menu(‘echo=0&orderby=name&exlude=181&title_li=&depth=1′)); ?>
I also wanted to get the current tab portion to work so that the currently open tab is highlighted. I did this by adding an additional replace for the list item (li) containing whatever was in the current $post->post_title.
This worked but broke when I used redirectors for parent pages (this is where you click on the parent and get redirected to one of its children pages, it’s helpful when you just want to categorize topics but not really talk about the categories themselves). To get around that, I check first to see if the current post has a parent(this works because I only have two layers, if you have more, I guess you’d need to add more checks but I can see where that could get messy).
If you’re not using redirection, just look at the snippet after the “else” statement.
if($post->post_parent) {
$parent = get_post($post->post_parent);
// Form menu items
$menu_li = preg_replace(‘@\]*)>\]*)>(.*?)\@i’, ‘$3‘, wp_list_pages(‘echo=0&orderby=name&exlude=181&title_li=&depth=1′));
// Find and replace selected tab list item%0pan>’.$parent->post_title.’(.*)\D
echo preg_replace(‘@\<li(.*)<s@i’, ‘<li id="current"$1′.$parent->post_title.’$3‘, $menu_li);
}
else{
// Form menu items
$menu_li = preg_replace(‘@\]*)>\]*)>(.*?)\@i’, ‘$3‘, wp_list_pages(‘echo=0&orderby=name&exlude=181&title_li=&depth=1′));
// Find and replace selected tab item
echo preg_replace(‘@\<li(.*)’.$post->post_title.’(.*)\@i’, ‘<li id="current"$1′.$post->post_title.’$3‘, $menu_li);
}
I have a question about this. What if I want to make it so whatever page you’re on, the button in the navigation bar has a different color to let you know you’re on that specific page? Is this possible with this hack?
Thanks for the nice and useful code
I was playing around today with the loopy replacement fix above and happened upon this page:
http://codex.wordpress.org/Template_Tags/wp_list_pages
“All list items (li) generated by wp_list_pages() are marked with the class page_item. When wp_list_pages() is called while displaying a Page, the list item for that Page is given the additional class current_page_item. ”
so basically instead of replacing any output coming from wp_list_pages, you can just create a CSS class to handle class_page_item and your buttons will be just as good! Even better, you won’t waste any precious processing on replacements!
thanks for this very useful code, i will try to use it to my blog
Hello Everyone,
I love this tutorial! However, I have not idea how to add this to my blog. I want this specific hack. People are saying its different for wp 2.8 and above. Also that codex link is something I don’t understand. Can someone guide me so I can add it to my wp site. I wanted two navigation bars so this is perfect! Can someone just post the code or something on how to do implement it? Please let me know.
Thank You
Can someone please post a link to this hack or codex implemented so we can see it in action?
Thx much!
Also no one commented on sunil’s post about a possible way to do this vertically. Any thoughts?
Thx Again!
hi,
thanks for info good sharing
To get around that, I check first to see if the current post has a parent(this works because I only have two layers, if you have more, I guess you’d need to add more checks but I can see where that could get messy
i am card blog admin.
i tried using this exactly same. I want to highlight active category item similar to Current_page_item. How to do it along with this span code added category list?
Thanks
WOW !!! SUPERB work man!!! great!
Thank you for this article. I have used it a few times and it works very well! For the first time I was using the exclude feature for the menu and it was not working. Upon staring at the word exclude for a while I realized that it was misspelled. No biggie. Just needed to add a “c”. Just wanted to let you know and thanks again!
Awesome! I was wondering how to modify the WordPress code in order to get sliding doors effect. But the code you provided worked for me. Thanks.
I have been trying to use the sliding doors technique with dropdown menus. Any tips or insight on using this technique for Parent links and being able to style the child links with their own look? In other words keeping the two visually different?