one often needs to define the first and last element in navigation menu. It is needed when you want to remove the last/first unwanted border or maybe if you want to highlight the first item differently. The effect can be achieved by adding an extra class “first” and “last” to the respective child elements of the menus. It is a much sought after feature and I feel should be made the default feature of joomla menu system.
Joomla has a mod_mainmenu module for creating menus. Joomla allows the users to create overrides to get this special enhancements. We would make an override to joomla’s ‘mod_mainmenu’ module to get out classification finctionality.
The overrides are placed in a folder named “html” inside your template folder. Inside ‘html’ place another folder called ‘mod_mainmenu’ to specify the override. Next, copy the file default.php from modules/mod_mainmenu/tmpl from your joomla filesystem to our folder(mod_mainmenu). I recommend you get your own file it may avoid any version related issues. Your default.php file is now located similar to:
templates/MYTEMPLATE/html/mod_mainmenu/default.php
open the file and navigate to the ‘ul’ component which looks like
if ($node->name() == 'ul') {
foreach ($node->children() as $child)
{
if ($child->attributes('access') > $user->get('aid', 0)) {
$node->removeChild($child);
}
}
}
We will add a few lines of code to this to get the ‘first’ and ‘last’ class in the menu items. Our new block will look like :
if ($node->name() == 'ul') {
foreach ($node->children() as $child)
{
if ($child->attributes('access') > $user->get('aid', 0)) {
$node->removeChild($child);
}
}
//NEW CODE STARTS HERE
$children_count = count($node->children());
$children_index = 0;
foreach ($node->children() as $child) {
if ($children_index == 0) {
$child->addAttribute('class', 'first');
}
if ($children_index == $children_count - 1) {
$child->addAttribute('class', 'last');
}
$children_index++;
}
//ENDS HERE
}
We are done. Just update the file on your webserver and test it. Now the menu child items must get classified. You can now use these classes to transform the look of its children elements.
little, but great modification.
exactly what I need.
Thank you!
Thanks for this post it got me on the right track to what I was trying to do. I needed a unique and predictable class on each and every menu item so I could style each one differently and whilst it needed a bit of adapting this was basically the answer.
Most excellent script. The only way I’ve been able to manage this so far is with CSS3 last-child which at present has limited support. Thanks to your help I now have cross browser joomla last-child alternative
THANKS!
[...] started poking around and ran into an August 2009 blog entry from Cecil Gupta that addresses the problem nicely. It shows you how to modify the menu code in [...]
Thank for this short and sweet script.
Excellent work. Thank You.
Hurray!!
aw, i love this mod
thanks
Ive tryied using this script for my joomla 1.5.15 pages and nothing seems to make it work. is this compitible with the latest version? i have a simple 1 level menu in Ul format (not the table format) and the first and last class will not get added… i dont understand this is simple i did exactly like stated. i also tried puttin it in templates/MYTEMPLATE/html/mod_mainmenu/default.php AND templates/MYTEMPLATE/html/mod_mainmenu/tmpl/default.php and no luck i even overrided the orginal one in the modules still nothing…. i need this to work badly
You need to check if you are even using the joomla native mainmenu module to render the menu. I doubt that because only then editing the files shall have no effect on the frontend. The trick applies till the latest version of joomla and works great.
Yup using mod_mainmenu the base menu included with joomla. i have a 2nd menu type installed in a diffrent position: http://box1.thegiant.ca/~belo/index.php?option=com_content&view=article&id=2&Itemid=2 the menu on the right is the one im trying to add the first last to. i changed the code you have above that starts on line 27 in the file default.php i really dont get why this isnt working. i tryied using a base joomla template and i still dont see the first last
Just tested the override on Joomla 1.5.17. Works cool for me.
Thank you for the great tip. I tried to migrate a Joomla site to a server running PHP 4.4.9 and noticed this did not work. The class name seemed to be over-ridden by the ‘item1′, ‘item2′, etc, rather than appended to it. Maybe this was the problem that Jonathan experienced. It worked great with PHP 5.2.9.
I have found that if you have any submenu items (children) under the first top-level item, the top-level item loses the ‘first’ class.
Just what I needed, thanks!
Thanks! you are a lifesaver!
(this should SOOOO be in the core!)
Thank you for your feedbacks
@Bobby: I have also noticed that the classes are not added if the menu item has any children, that is because the ‘parent’ class overwrites all classes instead of being appended.
To fix it, look for the following block of code in templates/MYTEMPLATE/html/mod_mainmenu/default.php, it should be directly after the code you’ve added above:
if (($node->name() == ‘li’) && isset($node->ul)) {
$node->addAttribute(‘class’, ‘parent’);
}
and replace it with:
if (($node->name() == ‘li’) && isset($node->ul)) {
if ($node->attributes(‘class’)) {
$node->addAttribute(‘class’, $node->attributes(‘class’).’ parent’);
} else {
$node->addAttribute(‘class’, ‘parent’);
}
}
Great! Probably the best post about some joomla module override. Worked at the first try. Simple, but perfect.
Great script!
Thank you!
I’ve got the question:
How to add both “first” and “last” class to one element?
I created new clas “first_and_last” and added code:
—————————
if ($children_count==1) {
$child->addAttribute(‘class’, ‘first_and_last’);
}
—————————
after
—————————
if ($children_index == $children_count – 1) {
$child->addAttribute(‘class’, ‘last’);
}
—————————
but its not the best solution
you code looks logical to me, doesnt it work right ?
@cecil
Yes, it works.
I wonder if is better way e.g.
add two classes ()
but I don’t know how to do it.
Yes, sure there is, just make it “first last”.
~’; I am really thankful to this topic because it really gives great information -,,
thanks for the solutions..
I am stuck in joomla 1.6 module. there is only mod_menu.. I succedded in adding class but bit wrong..
heres my code
$total = count($list);
$total_index = 0;
echo $total;
foreach($list as $ite){
//print_r($ite);
if($total_index == 0){
$class .= “first”;
}
if($total_index == $total – 1){
$class .= “last”;
}
}
$total_index++;
Will you be able to provide a version of your code to work with Joomla 1.6? The mod_menu module suffers the same lack of First and Last classes when creating menus. Thankyou.
Works perfectly. Yo can see effects on my website;]
Thx!
Aaah, just what I was looking for, thank you. This just saved many many hours today.
Just what i needed. Thank you.
Hi, this is awesome. It is hard for a begginer in joomla to figure out the component code myself to make changes (thanks joomla for you “simplicity”..). This is what I needed, thank you.
Hello, I just stop by to thank you for this. I need this for 2 days now, and thanks god that I found you!
I know this is an old post, but today, July 2011, it helped me A LOT!!!! I was breaking my head with lots of css designs, and this post really helped me. THANK YOU!
This is great!
It would also be good to know how to add a class to the anchor tag.
I need to move the ‘parent’ class from the li to the a but can’t see to find a way to do it……
That would make less sense in terms of styling. You can access the anchor tag through css using “li.parent a” rule and style it anything. I cant think of a situation where the “parent” class essentially has to be put to the anchor element.
I was trying to use this css menu http://www.lwis.net/free-css-drop-down-menu/
For some reason they have the parent class attached to the anchor.
In the end the template I was using for the menu didn’t fit with the site anyway so I just used one of the others and now it’s looking good.
Thanks for the first/last tip, you just saved me hours!
Awesome …. I was eagerly looking for it… Thanks to publisher
I don’t know if someone can readily answer this, but how would you apply the “first” and “last” to just the top levels and not the children?
First Item
First Child
Second Child
Last Item
Sorry, it posted it as HTML.
[ul]
[li class="first"]First Item
[ul]
[li]First Child[/li]
[li]Second Child[/li]
[/ul]
[/li]
[li class="last"]Last Item[/li]
[/ul]
great code
Thanks a lot