You Are Here: Using PHP To Highlight Navigation

When you walk into a mall, one of the first things you come to is a map with a "you are here" indicator that lets you know where you are. On a website, we can accomplish this by higlighting the current location on a navigation bar, menu, or list. Since the primary navigation is the most prominent feature on a website, we will discuss an easy way to do this with PHP.

Active or current navigation is big with usability nuts. Crucial’s website uses active navigation on the tabs and sidebar on every page. This visual indicator shows you exactly where you are, and will keep visitors to your website from getting frustrated and ultimately leaving.

Determine The Page Name

The first thing we need to do is come up with a naming convention for our pages. Some of the examples that I have seen make you label each page with a variable. This just seems like too much work. We will use the $PHP_SELF server variable to extract the actual filename, and use this as our reference point to setup the active navigation.

  1. <?
  2. $path = $_SERVER['PHP_SELF'];
  3. $page = basename($path);
  4. $page = basename($path, '.php');
  5. ?>

What this does is extract just the name of the file, and removes the .php file extension for redundancy’s sake. So if we were on a page called about.php, the $page variable would be equal to about.

The HTML & CSS

Now we need to build the structure for the navigation bar, and the CSS that will make everything all warm and fuzzy.

HTML

We are going to use a very basic navigation bar, and here is the markup for that:

  1. <div id="navbar">
  2. <ul>
  3. <li><a class="active" href="one.php">Page 1</a></li>
  4. <li><a href="two.php">Page 2</a></li>
  5. <li><a href="three.php">Page 3</a></li>
  6. <li><a href="four.php">Page 4</a></li>
  7. </ul>
  8. </div>

CSS

Now we will use CSS to jazz up the navigation bar, and set the style for the active navigation element to distinguish it from other elements.

  1. #navbar {
  2. height:30px;
  3. }
  4. #navbar ul {
  5. margin:0;
  6. padding:0;
  7. list-style:none;
  8. }
  9. #navbar ul li {
  10. display:inline;
  11. }
  12. #navbar ul li a {
  13. float:left;
  14. color:#fff;
  15. height:18px;
  16. margin:0 5px 0 0;
  17. border:1px solid #000;
  18. padding:5px 20px;
  19. text-decoration:none;
  20. background:#000;
  21. }
  22. #navbar ul li a:hover,
  23. #navbar ul li a.active,
  24. #navbar ul li a.active:hover {
  25. color:#000;
  26. border:1px solid #000;
  27. background:#fff;
  28. }

If we just use the HTML and CSS from above, we will end up with something like this:

Bringing It All Together

This is where the magic happens. Using an if-statement and our $page variable, PHP will determine what page a visitor is on and output the correct HTML to set the active navigation of an element:

  1. <div id="navbar">
  2. <ul>
  3. <li><a<? if($page == 'one') print ' class="active"'; ?> href="one.php">Page 1</a></li>
  4. <li><a<? if($page == 'two') print ' class="active"'; ?> href="two.php">Page 2</a></li>
  5. <li><a<? if($page == 'three') print ' class="active"'; ?> href="three.php">Page 3</a></li>
  6. <li><a<? if($page == 'four') print ' class="active"'; ?> href="four.php">Page 4</a></li>
  7. </ul>
  8. </div>

You can also use this same technique all over your website. You can create one convenient location to store page titles, keywords, and descriptions for your pages based on the filename and the $page variable.

Ultimately, this would best be done with a database, or at least functions that you can call anywhere, but this is a simple and effective way to increase the usability of your website with very little code.

Download The Code

Now that we have the individual elements, we’ll put the PHP code and HTML that should be outputted in a file called navigation.php, and we will simply call this file with a PHP include from any page that we want to output the navigation bar.

Click here to download the zip file.

Bookmark:  Del.icio.us · Digg · Furl · Google · Reddit · Technorati · Yahoo!

Subscribe Now

Subscribe to our blog by RSS or by email.

Related Posts

  1. Master Layout: Give Your Stylesheet A Friend
  2. Crucial 3.0: Web Hosting Evolves
  3. The $420 Design Contest
  4. Master Stylesheet: The Most Useful CSS Technique
  5. $4,000 Crucial Contest

Comments (54)

It worked! Thanks!
http://www.gilesward.net

When I use PHP for nav, I usually have all the HTML navigation in an external file (ex nav.php), included on all pages. Within that HTML navigation I include a class for each list element with the value of <?php echo $var; ?> with that variable being set on the page the file is included. Then in my CSS i have styling for that class, which can only be active on one page depending how I setup that variable. For larger sites, I do the PHP_SELF approach as well. Which brings me to another question, does it work when you have htaccess rewrite rules so “/about.php” is displayed as “/about”?

@Paul: I include a class for each list element

So you setup a CSS class for each item on the navbar? Do items on you navbar typically have different styles? I don’t really understand the reasoning behind this, unless each item looked different.

And regarding the mod_rewrite question, yes, it works with that as well because PHP still knows what the filename is.

Mich on 15 May 2007 said:

Hi

Your tutorial is excellent, worked a charm. I am a graphic designer with not much coding experience and I even managed to integrate it into a javascript expandable menu I am using.

My question is:

I have a drop down / expandable menu called “Projects” with sub navigation of “retail”, “commercial” and “residential”. As the expandable menu is closed when one of the subnavigation pages opens, I would like the menu item “Projects” to be highlighted. How do I change the code below so it adds an “active” class to my “projects” menu if the viewer is on a subpage?

(I assume that putting commas between the pages won’t work, eg. if($page == ‘projects, retail, commercial,residential,’)

This is the code I am currently using.

Thanks so much, any ideas are most appreciated.

Mich

Kyle on 16 May 2007 said:

Do you have a link to a working URL of this so I can better understand what you’re talking about?

And yes, putting commas between pages won’t work, you would have to use the or sign (OR, ||), e.g.:

if(($page == 'projects') || ($page == 'retail'))

Also, if you want to post code, wrap the code tag around it: <code> … </code>

Steve on 17 May 2007 said:

Something that works effectively also.

Assign each link on your menu an ID. So you would have, for a basic menu (3 items) - Home, About, Contact, giving you #home-link, #about-link, #contact-link.

In your PHP code (or whatever) assign an ID to the body tag telling it which page you’re on (so if you’re on the homepage, the body’s ID is #home.

In your CSS, this is the fun part:

#menu li { background-color: white; color: red; }
#home #menu #home-link { background-color: red; color: white; }

This of course assumes you’re using list items for menus. I’ve used this technique to great effect recently.

Kyle on 17 May 2007 said:

Steve,

The problem I have with that method is that you have to manually give each element in the navigation bar an ID. On top of that, you then have to assign an ID on the body tag of every page, or at least every page that would match up with the navigational element.

I like to keep the HTML as pure as possible, so going that route is counter-productive. It’s also twice as much work (and even moreso to maintain). It’s easier to let PHP do all the work, letting it extract the filename or even query if you take the dynamic route.

As for the CSS and HTML of the menu, why would you use anything other than a list element? That’s semantically the correct way to do navigation elements.

Also, let’s assume you expand this tutorial’s concept further, and use it to actively highlight sidebar elements. Are you going to go through each and every page giving every item on the sidebar an ID (and matching it up with the body tag)?

Dirk on 29 May 2007 said:

Hi, first of all, nice and clear tutorial. I really like the idea of using PHP for assigning an ‘active’ mode of links.
I would really like to use it, but I have another sitiuation which gives me some problems.
My site is build up using DIV’s, and I use a PHP include code to include my pages in to my [index.php].
The problem with your code is, that the current page is always index.php.
So my question is, not being much of a hero in PHP, if it is possible to make the if - statement dependable on the page that is currently included.

thanks in advance

This has worked beautifully for me up to a certain point. Thanks for the code! It’s genius! One question: When I’m using a cms (wordpress in my case) the php doesn’t know which page I’m on, since wordpress does not use file extensions for separate pages. If I can get past this I can make it work perfectly! The menu is up and running, it just always thinks it’s at home.

Thanks in advance!

Scott,

In the case of dynamic pages, you would have to do a bit of tweaking and either (a) use WordPress’ database or (b) use the query string variables. This would be the easiest to explain, so that’s what I’ll do.

I’m going by the website you typed in with this comment, meridiancrest.com, to explain this, hopefully it’s the website you’re talking about.

The structure of your pages is going to look like this:

1. Home (index.php)
2. About (index.php?page_id=1)

The number might not be the actual number, but you can find out what this is in a second.

What you have to do is use that variable, page_id=X, to setup the active navigation, instead of using just the $PHP_SELF variable, which is always going to come back as index.php.

This is the code you would use to pull the page ID:

$query = $_SERVER['QUERY_STRING'];
$query = explode('=', $query);
$query = $query[1];

If we’re on the about page, $query would be equal to 1.

So to make this work for you, you would add that snippet of code above right below the part that grabs the page name:

$path = $_SERVER['PHP_SELF'];
$page = basename($path);
$page = basename($path, '.php');
 
$query = $_SERVER['QUERY_STRING'];
$query = explode('=', $query);
$query = $query[1];

For your navbar, the home page is the only place where you would use this code:

<? if($page == 'index') print ' class="active"'; ?>

For other items on the navbar that are pages you setup in WP, you are going to use this piece of code instead:

<? if($query == 1) print ' class="active"'; ?>

Just change the number to the corresponding number for each page. If you don’t know what the number is, just login to the admin section of WP, go to Manage, and then select Pages. You can see the ID for each page that you have setup.

I hope I explained that ok, if not, I would have to see the site and how you have this setup. Let me know if that worked for you.

Kyle,

Thank you so much for the fast response. I am going to try this right now and get back to you :) I was about to try this the (bloated) javascript way, and in you come to save the day! I guess I’m not the only one up at 3:30am :P

Scott,

You’re welcome, and it’s only 12:30 here (Arizona time) but I’m always up late :D
It looks like you got it to work on your site though, so that’s good.

Also noticed you use ClickTale, cool website, eh? We put that on Crucial about a month ago and it’s been invaluable for usability testing.

Kyle,

I’ve read your instructions 3 or 4 times just to make sure I followed them to a T. I think I have done everything you’ve instructed, and am 1 step further but not all the way there just yet.

When I click the “About Us” tab, the “Home” tab stays active, also. Here is the site in question: southernally.com.

I’m so close I can taste it now! Haha. Thanks for the help.

Clicktale is awesome. I have a few other beta invites and what not you should holler at me on aim I will be glad to hook ya’ up. It’s “meridiancrest”.

Scott,

Ah, I see what the problem is. PHP is filling the $page and $query variable up, because while the page you are on is index.php, we need to distinguish between index.php and index.php with a query attached.

So it’s putting the class="active" bit on the index page (since we are on the index page), but also on the About Us page.

Ok, try this instead. For the home page, you are going to use this:

<? if(($page == 'index') && (!$query)) print ' class="active"'; ?>

For the About Us page, you are going to use this instead:

<? if(($page == 'index') && ($query == 6)) print ' class="active"'; ?>

Give that a shot and lemme know if it worked.

robin on 07 June 2007 said:

Hi,

I had an issue with this similar to Mich’s above. Is it possible to use a directory instead of page? Say I have a section of my site called events. Under “events” are a number of categories and within each category we regulary add new pages (with new page titles) Obviously it would be cumbersome to continue adding the name of each new event to the php code in the menu, but if each event category were it’s own directory… well that would work. Can it?

Hey Robin,

Yeah, that’s not a problem. This can work with pages, directories, and queries. To check for a directory you would do something like this:

$dir = getcwd();

Let’s pretend we’re on the following website and we ran that command:

domain.com/folder/file.php

If you run a website, you know that there’s a certain directory structure to your site, so if we were to echo the $dir variable, it would come out something like this (depending on your host because this can be done differently):

/home/username/public_html/folder

Now, that information might be useful to you, might not be, especially if you need to know the parent directories too. If you just want to know what directory you are in, you can add this right after the $path and $page code at the top of this article:

$dir = substr(strrchr(getcwd(), '/'), 1);

Using the website listed above, that would make $dir equal to folder. You can use that variable the same way you use the page variable:

$path = $_SERVER['PHP_SELF'];
$page = basename($path);
$page = basename($path, '.php');
$dir  = substr(strrchr(getcwd(), '/'), 1);
 
// Instead of copyring the HTML
// for the navigation list, I'm
// just going to show the code
// you would use with examples
 
// Single page
// domain.com/one.php
if($page == 'one') print ' class="active"';
 
// Single page in a directory
// domain.com/folder/one.php
if(($dir == 'folder') && ($page == 'one')) print ' class="active"';
 
// Multiple pages in a directory
// domain.com/folder/*.*
if($dir == 'folder') print ' class="active"';

Sometimes you might want something to always be highlighted if you’re in, say, a blog directory. Instead of setting up each page, you can have PHP just look at the directory name.

Hope this is what you were looking for. Enjoy!

robin on 08 June 2007 said:

Excellent. Thanks very much, I’m glad to have found your site.

Great article - it’s tough to find anyone helping newbies with the basics.

I am building a site where there are various “root level” pages which refer to “sub-pages” that I have put in subdirectories for neatness. Now this is a little off-topic, however what’s the correct PHP syntax for the link from one of the “root-level” pages into one of the sub-directories, e.g. “$site_root/subdirectory/file.php”.

To explain better, my menu is included in page1.php but it links to directory1/page2.php (where it’s also included). That’s all well and good, but as soon as I’m on page2.php within the subdirectory and I click on the next link to page3.php, it will look for directory1/directory1/page3.php, which doesn’t exist.

So using relative links is no good. I need to specify that the page exists at $site-root/directory/file.php. What is the correct way of saying this?

I have the menu highlighting perfectly, I just don’t have all my files in the same directory…

Jaclyn on 30 July 2007 said:

I have a website done entirely in html. Could I turn my navigation into a navigation.php file and include it on my html pages to get this same effect?

Certainly, you would just use the PHP include function:

<?php include('filename.php'); ?>

Hey Kyle!

Just wanted to say - thanks for this! It worked like a charm - you are amazing. I’ve also been snagging your “master stylesheet” heh!

- Steph

Kyle,
I tried your active page assignment code on this test page:
http://sevenstarssoap.com/test/index.php, where I use the same page to deliver a four-page site.

This code worked as expected.

You saved me a lot of time and I thank you very much for sharing your code. BTW I found your blog via the number one spot on the big G for this search phrase -

“you are here” php navigation

- congrats!!!
Have a beautiful day!
Liz

Hey Liz,

Glad it came in handy :)
Have a good one,

Kyle

Alice on 03 September 2007 said:

Hey Kyle, thanks SO MUCH for putting up this tutorial, I’ve been looking for one like this for a while now, but every time I looked I couldn’t get what I was looking for. But your tutorial is PERFECT! Thanks so much for making it! :D

Kyle -
Firefox likes your method just fine, but IE7 is choking on the first tab. IE doesn’t even show the link or the background images for the first (home) tab. What’s up with that?

Here’s my test page (again): http://sevenstarssoap.com/test/index.php

Any suggestions on how to combat this problem?
I’m still searching!
Thanks,
Liz

Kyle - the problem with IE was mine, not yours. I was missing an angle bracket to close out the first list item. I guess I just could not see that tree!

Thanks again for your great code!
Liz

Reza on 14 September 2007 said:

Hi Kyle. It really Worked!!! Thanks a lot. I was just trying to find such a great handy code. Thanks Kyle for sharing the code.

Alice: Glad you like it!

Liz: No problem, good to see you got it working.

Reza: You’re welcome, again, good to see that everyone’s finding this useful.

Jay on 12 November 2007 said:

Hi Kyle,

Firstly wanted to thank you for sharing this code. I’ve been searching for days to find a way to do what you’ve explained so well in this tutorial.

I’m a designer of sorts and not at all familiar with PHP. I’ve managed though to implement your script into this website www.davidhannan.com.au . I’ve not yet quite achieved the desired result I was hoping for however.

I’ve attempted to add the $dir  = substr(strrchr(getcwd(), '/'), 1); to allow the script to work with directories as you explained in the previous comment response to Robin.

If you click through a few of the pages within the above website you’ll see obvious problems. Wondering if you would please consider providing me some assistance to get this to work correctly?

Ideally when a user clicks into a sub-section (a sub-directory) via the drop-line menu I’d still like the “You Are Here” button effect to remain visible. All the entry pages to each site section are also called index.php - this is causing some confusion within the script also.

Thanks again!
Jay

Below is the code I’ve placed in the websites top.php require file

<a href="/index.php" rel="nofollow">Home</a>
<a href="/about/index.php" rel="nofollow">About</a>
<a href="/products/index.php" rel="nofollow">Products</a>
<a href="/equipment/index.php" rel="nofollow">Equipment</a>
<a href="http://stockfootage.davidhannan.com/" rel="nofollow">Stock Footage</a>
<a href="/news/index.php" rel="nofollow">News</a>
<a href="/resources/index.php" rel="nofollow">Resources</a>
<a href="/contact.php" rel="nofollow">Contact Us</a>

Jay,

Ah, I see why that doesn’t work. See, the home page is index.php, but all of the pages in your directories are also index.php, so it would highlight both the Home button and whatever directory you are in.

To fix that you would need to change the code for the Home button area. Something like this should work:

<? if(($page == 'index') && ($dir == 'public_html')) print ' class="active"'; ?>

That should do the trick. It will only highlight the Home button if it’s in the root directory and the page is index.php. You will need to replace public_html with whatever your public directory is named, but it’s usually this.

Jay on 12 November 2007 said:

Thanks Kyle,

I’ve done as you’ve instructed and the index page name problem has been corrected. Thanks again!

Any ideas how to retain the “You are here” button effect when for instance someone accesses the about –> profiles page http://www.davidhannan.com.au/about/profiles.php ?

Jay,

Yeah, as long as you have this:

<? if($dir == 'about') ... ?>

It should work, because profiles.php is in the about directory (I assume).

Jay on 13 November 2007 said:

Hi Kyle,

That’s brilliant - thanks again!

One more thing I’ve come across: what should the $dir = be when the site goes 3 or more directories deep?

I’ve got a static news section http://www.davidhannan.com.au/news/latest-news/latest-news.php .
Pages contained in the davidhannan.com.au/news/ directory display the “you are here” primary navigation tab fine as to be expected but as soon as the user accesses pages within the next directory down davidhannan.com.au/news/latest-news/ this disappears (again to be expected). I’m assuming I need to change something in this line of code or add another line that’s similar?

$dir  = substr(strrchr(getcwd(), '/'), 1);

Sorry to be a bother. Your help but is being greatly appreciated,
Jay

You would just keep adding more directories to the list:

<? if(($dir == 'about') || ($dir == 'news') || ($dir == 'bleh')) ... ?>

Dave on 28 December 2007 said:

I know this is an old post, but I need a little help.

My query string variables look like the following:


http://mysite.com/index.php?mainCat=Televisions&amp;subCat=Plasma-TVs

Thanks in advance.

Mandy on 06 March 2008 said:

I have used this navigation technique and it’s worked well…but for this project I have a vertical navigation that has different sized buttons (different heights with different background images to match the different heights). I want to highlight each section, but I’m having trouble because I needed to use a class to define the different button sizes (.small, .medium and .large) and it put it in the tag but then I also need to use the .active class to highlight the button…but the problem is I can’t seem to get the background image to highlight when the page is active. The buttons appear, they highlight when hovered and the text even appears bold when on an active page, but the background will not highlight on an active page. My thought is because I can’t have both classes working together (.active and .small?):

Here is the code:


#navbarvert{
overflow:hidden;
width: 100%;
}
#navbarvert ul {
margin-top: 20px;
margin-left: 6px;
padding:0;
list-style:none;
}
#navbarvert ul li a {
display: block;
font: 11px Arial;
text-decoration: none;
line-height: 15px;
text-align: center;
}
 
/* ------for vertical nav button #1 ------- */
 
#navbarvert ul li.small {
float: left;
background: transparent url('../images/short.gif') no-repeat top left;
width: 154px;
height: 38px; /* Height of button background height */
padding: 8px 0 0px 0;
}
 
#navbarvert ul li a.active {
font-weight: bold;
}
#navbarvert ul li.small:hover,
#navbarvert ul li.small.active,
#navbarvert ul li.small.active:hover {
background-position: top right;
}

And here is the include file for the left nav:

 
<a href="1express.php" rel="nofollow">Express Greetings &amp;Social Courtesies</a>
<a href="2give.php" rel="nofollow">Give and FollowDirections &amp; Sequence</a>
<a href="3express.php" rel="nofollow">Express Needs, Likes &amp; Feelings</a>
<a href="4ask.php" rel="nofollow">Ask and AnswerClarifying andInformational Questions</a>
<a href="#" rel="nofollow">Participate in Conversations and Discussions</a>
<a href="#" rel="nofollow">DescribePeople and Things</a>
<a href="#" rel="nofollow">Describe Places</a>
<a href="#" rel="nofollow">Describe Actions</a>
<a href="#" rel="nofollow">Describe Spatial andTemporal Relations</a>
<a href="#" rel="nofollow">Compare &amp; Contrast</a>
 

I am trying to use dynamic links with PHP on mine but I need it not only to highlight, I need it to be able ot dynamically link up to 4 directories deep. Any ideas how I can achieve this using your highlight function also?

So far I use:

 

And this method works well from my navigation menu with a link like this:

<a href='index.php?category=dir&amp;page=mypage' rel="nofollow">My Active Link</a>

and now with highlighting:

&lt;a href="index.php?category=dir&amp;page=mypage"&gt;

Problem is the code I have to include the linked page dynamically, how can I make it work with pages 4 directories deep?

I am trying to use dynamic links with PHP on mine but I need it not only to highlight, I need it to be able ot dynamically link up to 4 directories deep. Any ideas how I can achieve this using your highlight function also?

So far I use:

  $category = $_GET['category'];
  $page = $_GET['page'];
  if (!empty($page)) {
    $page .= '.php';
    include($category . '/' . $page);
  }
  else {
    include('dir/default.php');
  }

And this method works well from my navigation menu with a link like this:

<a href='index.php?category=dir&amp;page=mypage' rel="nofollow">My Active Link</a>

and now with highlighting:

&lt;a href="index.php?category=dir&amp;page=mypage"&gt;

Problem is the code I have to include the linked page dynamically, how can I make it work with pages 4 directories deep?

You must use PHP for any kind of common code across pages and navigation is the perfect place for this. It makes it so much easier to maintain and update and make changes to your site. The techniques here are a good idea.

I love PHP and this is one of my favourites, but today I have to do this with ASP… So searching in Google I didnt find any interesting / useful, so I made my own tip…

Link:
http://www.tomasdev.com/blog/2008/04/09/how-to-highlight-menu-item-with-asp/

Excellent tip, thanks. managed to integrate it into “sliding doors” and osc where there were gaps into a site I am working on - tabs on top there in grey http://www.4wheelplay.co.uk.

also used the body id tag

Umar on 10 June 2008 said:

Very good concept. With a bit of tweaking you can do much more

Dan on 15 July 2008 said:

Thank you very much for this tutorial, works like a charm! Is there anyone who has an answer to Dirk’s post - http://www.crucialwebhost.com/blog/you-are-here-using-php-to-highlight-navigation/#comment-255. I just wanted to ask about the same thing.

@Dan:

Could you post an example page on pastebin or something?

Dan on 15 July 2008 said:

Hi Kyle,

index.php - http://pastebin.com/m6bd3d71f
func.php - http://pastebin.com/d4efe2c66
navigation.php - http://pastebin.com/d77a79567

Thanks in advance :)

Dave:

Ah, well instead of looking for the page name, just go by the $_GET variable:

Replace the following:

$path = $_SERVER['PHP_SELF'];
$page = basename($path);
$page = basename($path, '.php');

With this:

$page = $_GET['id'];

Your HTML output will remain the same, we’re just changing where we check for the page name, so instead of the actual filename (less extension), we just use the ID variable.

Hope that helps.

Dan on 15 July 2008 said:

Got it. Works perfectly! I finally understood how it works. Again .. thank you very much for you help, this tutorial and your time!

Dan:

No problem, glad it’s working :)

Sharlene on 13 August 2008 said:

This is a great tutorial! Thanks!

Trackbacks & Pingbacks

  1. Misty Breeze * + .
  2. Tomas Roggero || Web Developer » Blog Archive » How to highlight menu item with ASP
  3. web hosting basics
  4. News Stock Footage

Leave A Reply

Helpful Hint

To post HTML or other code, wrap your text in the <code> tag.