PHP and CSS menu help

Soldato
Joined
7 Jun 2003
Posts
6,234
Location
Leicestershire
Hey

I am drafting a new website, and having some issues with highlighting the parent page when on a child page. I will explain what system I am using, and then what I have tried.

For a single top level item, I use:

PHP:

Code:
<?php $currentPage = basename($_SERVER['SCRIPT_NAME']); ?>

at the top of the page, followed by:

Code:
<ul>
<?php echo "\n"; if ($currentPage == '#') { ?><li class="on">News</li><?php } else { ?><li class="off"><a href="#">News</a></li><?php } ?>
</ul>

And for drop downs:

Code:
<li><a href="#" class="none">About</a>
<ul>
<?php echo "\n"; if ($currentPage == 'club.php') { ?><li class="on">Club</li><?php } else { ?><li class="off"><a href="../club.php">Club</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'coaches.php') { ?><li class="on">Coaches</li><?php } else { ?><li class="off"><a href="../coaches.php">Coaches</a></li><?php } ?>    
<?php echo "\n"; if ($currentPage == 'officials.php') { ?><li class="on">Officials</li><?php } else { ?><li class="off"><a href="../officials.php">Officials</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'management.php') { ?><li class="on">Management Team</li><?php } else { ?><li class="off"><a href="../management.php">Management</a></li><?php } ?>
</ul>
</li>
</ul>

Styled with:

CSS:

Code:
.nav {
width: 990px;
height: 60px;
}

.nav ul {
margin-left: 0px;
padding-left: 0px;
width: auto;
}

.nav ul li {
float: left;
list-style-type: none;
position: relative;
}

.nav ul li a {
color: #666;
font-size: 14px;
text-decoration: none;
background-color: #fff;
display: block;
height: 36px;
width: 110px;
text-align: center;
line-height: 36px;
padding-bottom: 0px;
}

a.none {
cursor: default;
}

.nav li:hover > a {
background-color: #181d63;
text-decoration: none;
color: #fff;
}

.nav ul ul {
position: absolute;
visibility: hidden;
display: block;

}

.nav li ul li a {
background-color: #e5e5e5;
color: #000;
top: 38px;
text-align: center;
font-size: 12px;
}   

.nav li ul li a:hover {
background-color: #CCC;
color: #000;
top: 38px;
text-align: center;
}

.nav li:hover ul {
visibility: visible;
background-color: #181d63;
}

.on { 
color: #fff;
font-size: 14px;
text-decoration: none;
background-color: #181d63;
display: block;
height: 36px;
width: 110px;
text-align: center;
line-height: 36px;
cursor: default;

}

.off { 

}

This works well and highlights the page that is open, be that in the top level or drop down. I would like to make it so that being on any of the child pages will also highlight the top level parent.

I have tried:

PHP:

Code:
<ul>
<li><?php echo "\n"; if ($currentPage == 'club.php') { ?><li class="on">About</li><?php } else { ?><li class="off"><a href="#" class="drop">About</a><?php } ?>
<ul>
<?php echo "\n"; if ($currentPage == 'club.php') { ?><li class="on">Club</li><?php } else { ?><li class="off"><a href="../club.php">Club</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'coaches.php') { ?><li class="on">Coaches</li><?php } else { ?><li class="off"><a href="../coaches.php">Coaches</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'officials.php') { ?><li class="on">Officials</li><?php } else { ?><li class="off"><a href="../officials.php">Officials</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'management.php') { ?><li class="on">Management Team</li><?php } else { ?><li class="off"><a href="../management.php">Management</a></li><?php } ?>
</ul>
</li>
</ul>

And adding the following to the css:

CSS:

Code:
a.drop {
}

a.drop:hover {
visibility: visible !important;
}

At this point, I run in to two things.

1. Being on the 'club.php' page now highlights the 'About' parent.
I'm not sure how to add to the php to incorporate all it's child pages. ('club.php', 'officials.php') doesn't seem to work.

2. Although the parent is now highlighted, that menu item no longer drops down.

I think I need to create an .onchild condition that when applied to a top level parent, still allows a drop down, but I'm really quite stuck on how to go about this, and seem to be deviating ever further from my original code! I think I've been staring at it too long.

I am keen to keep this all in PHP and CSS without resorting to jquery if possible.

Thanks,

James
 
Not the neatest solution but this should work

Code:
<ul>
<li><?php echo "\n"; if ($currentPage == 'club.php' || $currentPage == 'coaches.php' || $currentPage == 'officials.php' || $currentPage == 'management.php' ) { ?><li class="on">About</li><?php } else { ?><li class="off"><a href="#" class="drop">About</a><?php } ?>
<ul>
<?php echo "\n"; if ($currentPage == 'club.php') { ?><li class="on">Club</li><?php } else { ?><li class="off"><a href="../club.php">Club</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'coaches.php') { ?><li class="on">Coaches</li><?php } else { ?><li class="off"><a href="../coaches.php">Coaches</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'officials.php') { ?><li class="on">Officials</li><?php } else { ?><li class="off"><a href="../officials.php">Officials</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'management.php') { ?><li class="on">Management Team</li><?php } else { ?><li class="off"><a href="../management.php">Management</a></li><?php } ?>
</ul>
</li>
</ul>
 
Tidy it up by putting the page names in a hash with their links such as:
PHP:
$textForPages = array("club.php" => "Club", "coaches.php" => "Coaches" /* etc */);
$current = basename($_SERVER['SCRIPT_NAME']);
Then you can check if it's a page you want the about thing to display:

PHP:
if (isset($textForPages[$current])) { 
  echo "<li>About</li>";
  echo "<li>" . $textforPages[$current] . "</li>"; 
} else {
 /* whatevs here */
}

forgive any syntax errors. It's been years since I have used php.
 
Not the neatest solution but this should work

Code:
<ul>
<li><?php echo "\n"; if ($currentPage == 'club.php' || $currentPage == 'coaches.php' || $currentPage == 'officials.php' || $currentPage == 'management.php' ) { ?><li class="on">About</li><?php } else { ?><li class="off"><a href="#" class="drop">About</a><?php } ?>
<ul>
<?php echo "\n"; if ($currentPage == 'club.php') { ?><li class="on">Club</li><?php } else { ?><li class="off"><a href="../club.php">Club</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'coaches.php') { ?><li class="on">Coaches</li><?php } else { ?><li class="off"><a href="../coaches.php">Coaches</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'officials.php') { ?><li class="on">Officials</li><?php } else { ?><li class="off"><a href="../officials.php">Officials</a></li><?php } ?>
<?php echo "\n"; if ($currentPage == 'management.php') { ?><li class="on">Management Team</li><?php } else { ?><li class="off"><a href="../management.php">Management</a></li><?php } ?>
</ul>
</li>
</ul>

Thank you both. :cool:

This works perfectly to resolve issue 1. It keeps it a bit simpler at the moment too as theres 5 drop downs and I can keep them 'separate' for now with this.

All child pages of 'About' now make the 'about' be highlighted in menu, but hovering that item still won't drop the menu. Other menu items drop as normal. Any ideas on this bit?

Thanks,
 
PHP:
<?php
  // Stick this with your helper functions
  function buildMenu($navigation, $currentPage){
    echo '<ul>';
    foreach ($navigation as $key => $val) {
      $class = $val === $currentPage ? 'on' : 'off';
      echo '<li>';
      if( is_array($val) ){
        echo '<a href="#" class="' . $class . '">' . $key . '</a>';
        buildMenu($val, $currentPage);
      } else {
        echo '<a href="' . $val . '" class="' . $class . '">' . $key . '</a>';
      }
      echo '</li>';
    };
    echo '</ul>';
  };

  // Define current page
  $currentPage = 'club.php';

  // Build up your navigation arrays
  $navigation = array(
    'News' => '#',
    'About' => array(
      'Club' => 'club.php',
      'Coaches' => 'coaches.php',
      'Officials' => 'officials.php',
      'Management' => 'management.php'
    )
  );

  // Build HTML
  buildMenu($navigation, $currentPage);

Keep things DRY (Don't Repeat Yourself) and save yourself the trouble when it comes to amending the markup.


BTW don't use the above, this is just a quick brain dump - although it should work it could also be improved lots.
 
Last edited:
That snippet will build the nested up structure you described if you wanted to test and understand it.
 
I'm on my laptop now Phunky and actually looking at it as a whole it makes very good sense. I shall have a play around with it. Thanks :)
 
Back
Top Bottom