Prestashop top menu: add ‘active’ state for current page

It seems that many people are having trouble in targeting the “current” state for a link in the Prestashop top menu. In this quick tip, we will see how to do it, and we’ll also go beyond the basics and show the topmost parent for current subcategories and other pages.

  • Version used: Prestashop 1.5.3 (compatible with all 1.5 top menus)

Step 1 – Inspecting the Prestashop top menu and preparing files

First of all, let’s have a look at the top menu, and see what can be done to target the “current” class. Click on any top level category of your shop, and fire up your favorite debugging toolbar (I’ll use Chrome Developer Tools in this example)

Prestashop top menu with active state - current link inspection

The current element has the sfHoverForce class assigned

 

As you can see, when in a category, that very same link’s parent is given the class sfHoverForce. Easy enough to target, isn’t it?

Now, it’s bad practice to directly edit core files, therefore we will use an override for the stylesheet, and another one for the javascript. Go to the modules folder, then blocktopmenu, and copy the css/ folder. Reach your theme folder, open css/, and, if not already there, create a new subfolder called modules. Inside it, create a new folder named blocktopmenu, and finally paste the css folder inside this.

You might also want to copy the entire img/ folder of the module inside this one (not css/, the parent), so that you can see images.

For the javascript, go back to the original module’s folder, open js/ and copy superfish-modified.js. Again, in your theme’s folder, open js/, then modules/ (which should already be there, if not, create it), and create another folder named, useless to say, blocktopmenu. Inside it, create one last folder called js, and paste the superfish file inside it.

If you did it correctly, you should have the following structure:

  • theme_name/css/modules/blocktopmenu/css/superfish-modified.css
  • theme_name/css/modules/blocktopmenu/img/all image files…
  • theme_name/js/modules/blocktopmenu/js/superfish-modified.js

If not, or if all this sounded like vodoo magic to you, have a look at the official Prestashop documentation about overriding a module’s default behavior.

Step 2 – Adding the current menu item’s style

Now that our files are properly setup, open up superfish-modified.css (not the original one, but the one you copied over in the theme’s folder). Please note that I’m using the default Prestashop template for this example. Let’s target our “current” class first. At the end of the file, add the following style:

.sf-menu > li.sfHoverForce > a{
	background-color: white;
	color: #000 !important;
	text-shadow: none;
}

Explanation: Just some ordinary css. I’m targeting the anchor tag(a) which is direct descendant of the shHoverForce-classed li, which is itself direct child of the topmost menu element. I’m doing this, and with descendant selectors, since I don’t want any other sub-link to have the “current” state’s white background, but only the top level ones. Of course, if you do want it, feel free to use a regular selector. Also note that I’m just using some ordinary styles for demonstration purposes; feel free to change the values as you like.

If we now reload the page, we will see something like this

Prestashop top menu with active state - current page added

The link to current page now shows as “active”

 

NOTE: the top menu block is bugged in 1.5.3.1 (with chrome at least). Therefore, when you’re in a category, not all subcategories will show up in the menu. Fixing it is beyond the scope of this tutorial, thus I will not cover it.

You will see we are currently targeting the actual category we are in. But what if we are in a subcategory, or other pages? Let’s look at the other pages first, and the class they have been assigned.

I created 2 more links in the top menu, one linked to a product (the Belkin Folio) and another one linked to a CMS page. By inspecting those links when in the respective pages, I can see they’ve been assigned the sfHover class. Weird. This is not consistent, Prestashop Team! … But let’s put complaints aside and deal with it. We could target that class, of course, but that’s also the name of the class assigned to an element when hovering on it with the mouse, and this is bad if we want to have two separate styles. We’ll need to add some javascript to handle this.

Step 3 – Target other pages and subcategories

First, open up superfish-modified.js (again, the override!). Locate the jQuery wrapper at about line 122 (Prestashop 1.5.3.1). You will see something like this:

jQuery(function(){
	jQuery('ul.sf-menu').superfish();
});	

Inside that wrapper, after the superfish() function call, add the following

	$('.sfHover').addClass('sfHoverForce'); // will only target current links, since it's fired upod page load

And this way, as written in the comment, we are appending our sfHoverForce class to the elements that already have .sfHover when the page loads (therefore, we don’t affect any further hover state). refresh the product or CMS page, and you’ll see it’s now properly targeted. Cool, but we’re not done yet. I added a subcategory to Accessories, and I can see Accessories itself is not set as “current” if I’m in that subcategory. We have to fix this, and it will be a bit more complex. In the very same javascript file, add the following code after that last one we just wrote:

	function recursiveCheck(element)
	{
		if (!element.length)
			return;
		var the_ul = element.parent(); // unordered list parent
		if (the_ul.hasClass('sf-menu'))
			element.addClass('sfHoverForce'); //means it is another list item, add the class
		else recursiveCheck(the_ul.parent());
	}
	recursiveCheck($('.sfHoverForce'));

Explanation: wait! Don’t run away! First we create a “recursive function”. This function grabs the current sub-link with the class sfHoverState as the only argument. First, it checks that there currently is at least one element with that class applied. If not, it breaks, otherwise we might end up in an infinite loop. It then creates a variable for its direct parent (the unordered list). If this parent is the top most menu element (with the class sf-menu) we add the sfHoverForce class to the current list item. If not, we call the very same function again, and this time the argument we pass is the parent ul’s parent, therefore another list item, one level higher than our first one. We go on with this until we reach the top level, and add the current state to our top level link. This will work with the many sub-category levels you can imagine. Lastly, we call the function by targeting the only link that currently has the sfHoverForce class as the page loads (alas, our subcategory in this case).

Prestashop top menu with active state - finished result

Finished result. This will work with all pages & subcategories

 

Reload the page in any subcategory, and you should have the links as you want!

You like the tuts and want to say "thank you"? Well, you can always feel free to donate:

  • http://jawarentcar.com jazz rentcar

    how to make the blocktopmenu to sidebar menu?

    http://www.jawarentcar.com

  • hong tran dinh

    thank u very much.
    first time ,i’m was suscess in v1.5.6
    but today i using v 1.6.0.6 this not working.
    and this my method .

    $(function() {
    var pgurl=window.location.href;

    $(“ul.sf-menu li a”).each(function(){

    if($(this).attr(“href”) == pgurl || $(this).attr(“href”) == ” || $(this).attr(“href”) == pgurl+’#’ )
    $(this).addClass(“active”);
    })
    });

    and style by my class .active (i’m sorry, english language very bad :d)

  • Laura

    Is it possible that the first = homepage also remains active with sfHoverForce class?

    Thank you very much for your help.

    Greetings.

    • Sylvain

      It would be nice if someone could help for this too.

      Very good and well done tut !

      Greetings

  • http://test.zaluno.si Rok

    Hi!

    I tried using your methods to highlight the top menu. It only works partially. I also used suggestion to modify the blocktopmenu.php file from one of the replys but my site dissappears in that case. Did I paste the extra js code correctly into the file?


    })(jQuery);
    jQuery(function(){
    jQuery('ul.sf-menu').superfish();
    $('.sfHover').addClass('sfHoverForce');
    function recursiveCheck(element)
    {
    if (!element.length)
    return;
    var the_ul = element.parent();
    if (the_ul.hasClass('sf-menu'))
    element.addClass('sfHoverForce');
    else recursiveCheck(the_ul.parent());
    }
    recursiveCheck($('.sfHoverForce'));
    });

    As in partially I mean that when I visit the main category, it gets properly highlighted. Subcategories do not highlight and connected upper category also remains the same.

    What am I doing wrong?

    You guys are awesome at this, this is the only proper post on the internet that got me in the right direction.

    (Prestashop 1.5.4., test.zaluno.si)

    • http://test.zaluno.si Rok

      OK I cleared my cache and server cache after whole day of coding and I get highlight on category while visiting subcategory. Only trouble that remains is highlighting participating subcategories in topmenu.

  • Daniel

    Hi,

    Thank you for this tutorial. I have one problem. When i go on the homepage of the site, the “HOME” button doesn’t change color. I made the home button like a CMS with the link to home. Could you please help me. I see that on your site the home buton gets white when i am at the homepage.

    Thanks in advance!

  • Yury

    Hi, and in the product page?? :(

    • DaRk

      Hey !
      Have you found a solution?
      Same need for me :(

    • DaRk

      I’ve found a solution, if you’re interested
      In blocktopmenu.php,
      Ln 638 on function getCategory([...]) below ‘$selected = [...]‘, added the folowing
      if (Tools::isSubmit(‘id_product’))
      {
      if (!isset($this->context->cookie->last_visited_category)
      || !Product::idIsOnCategoryId($id_product, array(’0′ => array(‘id_category’ => $this->context->cookie->last_visited_category)))
      || !Category::inShopStatic($this->context->cookie->last_visited_category, $this->context->shop))
      {
      $product = new Product($id_product);
      if (isset($product) && Validate::isLoadedObject($product))
      $this->context->cookie->last_visited_category = (int)$product->id_category_default;
      }
      $selected = ((int)$this->context->cookie->last_visited_category == $id_category) ? ‘ class=”sfHoverForce”‘ : ”;
      }

      Taken from blockcategories module.
      It works good for me.

      • Laurent

        This issue is working !

        But don’t forget to put

        $id_product = (int)Tools::getValue(‘id_product’);

        Just before the code you mentioned :)

        in order to avoid warnings.

  • Adrian

    Hi. I have a problem. A weird problem with this. Look here http://vps13494.ovh.net/clients/cagole/index.php .All works perfect except contact (last menu). Please help me with this.

  • http://www.m2creation.fr Paul R

    Hello,

    Works for categories but does not seem to work for cms pages.
    Maybe I’m putting the js bit in the wrong place.

    I write :

    jQuery(function(){
    jQuery(‘ul.sf-menu’).superfish();
    $(‘.sfHover’).addClass(‘sfHoverForce’); // will only target current links, since it’s fired upod page load;

    });

    Please let me know,

    thanks in advance!
    paul

  • virginielh

    I’ve implemented your solution, but it highlights the whole sub-menu. I’d like to have only the selected sub-category + the parent category to be highlighted. Would you have an idea on how I can do this? Thanks you!

    • http://nemops.com Nemo

      You might have missed the “>” decendant selector

    • em

      I have the same problem. Solutions? Thank You!

    • jcar98

      I also have this issue and I did check for the “>” descendant selector and it is there. Did anyone find a solution?

  • Hali

    Thank you!

    • radus

      Hi,

      was this suppose also to “tranform to active” current page url inside breadcrumb ?

      [ I do not arrive there ]

      thanks again,

      r

      • http://nemops.com Nemo

        Hi,
        Uhm…no, not that i noticed at least… does it?

Advanced Web Hosting for only $4/month

Store Top Sales

You like the tuts and want to say "thank you"? Well, you can always feel free to donate: