active navigation item

Tourist
4 0 1
I'm using some fairly standard code for my main nav in my layouts file: <ul id="nav" class="clear">
{% for link in linklists.main-menu.links %}
<li>{{ link.title | link_to: link.url }}</li>
{% endfor %}
</ul> is there anyway to make the page that the user is currently on to have a span tag with a class of active instead of the anchor tag inside the list item?
0 Likes
New Member
1 0 0

In general, without the ability to use if/elseif structure and to utilize custom variables it is very difficult to identify which link should be considered active.

I am creating a store with a set of tabs :

Home, Collection (type1), Collection (type2), etc

Something like : Home | Jackets | Shirts | Pants

If a user is on the Collections page or a product page for a product within one of the defined collection pages I want to show that tab as the current tab.

General logic would be :

{ for link in linklists.main-menu.links }
var navid = "" 
If (template = "index" AND link.title = "home")
   navid = "id=current" 
else if (template = "collection")
   if (collection.title = "Jackets AND link.title == "Jackets")
      navid = "id=current" 
  ...
  end if
else if (template = "product") 
   if (product.type = "JACKET" AND link.title = "Jackets")    
      navid = "id=current" 
   ...
end if
<li {{navid}}>{{ link.title | link_to: link.url }}</li>
{ endfor }

This is not very elegant but it is the logic I want. If liquid does not support this type of simplistic logic it painfully limits what is possible. Please advise, is it possible to do something like this ?

0 Likes
Shopify Staff
Shopify Staff
2002 0 44

I was typing an elaborate response to this showing how it can be accomplished using CSS but hit a brick wall. Difficoult issue you have there!

The only currently working solution i can offer would be JS



$$('a').each( function(link){ 
  if (link.href == document.location.href) {   
    Element.addClassName(link, 'active'); 
  }; 
});

Hope this helps.

I’m wondering if these pains are just a good indication of a missing filter in the standard library though…

Tobias Lütke - Shopify CEO // http://twitter.com/tobi
0 Likes
Tourist
4 0 1

It’s not ideal, but it works. It would be nice if there was an attribute under page that gave the current URL so I could use if statements to completely remove the anchor tag and place a span, but this works for this project. For others with the same problem I’ve expanded the code just slightly and included it below

function makeActive() {
 $$('#nav a').each( function(link){ 
  if (link.href == document.location.href) {  
   Element.addClassName(link, 'active')
  }
 })
}
Event.observe(window, 'load', makeActive, false)

You can see it in action at http://www.4zproducts.com

0 Likes
Tourist
4 0 1

tobi: I was thinking something like -

{ for link in linklists.main-menu.links }
 { if link.url == page.url }
  span class="active">{{ link.title }}/span>
 { else }
  {{ link.title | link_to: link.url }}
 { endif }
{ endfor }
1 Like
Shopify Partner
253 0 1

I see you have highlight_active_tag for the tags, do you have something similar for linklists?

Something I ran into when building the Dropify theme was that it works better in that specific design to mark the list item as active instead of the link itself. If there were a highlight_active_class for URLs that could be placed in the containing elements as well, it would make theming much more flexible.

Making it obvious where the customer is at all times, especially in a drill-down, is rather important for usability, so any options would pretty much rock.

Cliff Spence
1 Like
Tourist
4 0 1

Ack! I forgot to close my anchor tag…

There. ;)

0 Likes
New Member
2 0 0

Great suggestions, thank you. However, in my situation I need one more level of recognition when a product page is selected it will not have the same url as the navigation url. I ended up doing it this way by using conventions when naming collections, product types, and top level navigation :

{% for link in linklists.main-menu.links %}
{% case template %}
{% when 'index' %}
   {%if link.title == 'Home'%}
      <li id="current">{{ link.title | link_to: link.url }}</li>
   {% else %}
      <li>{{ link.title | link_to: link.url }}</li>
   {% endif %}
{% when 'collection' %}
   {% if collection.title == link.title %}
      <li id="current">{{ link.title | link_to: link.url }}</li>
   {% else %}
      <li>{{ link.title | link_to: link.url }}</li>
   {% endif %}
{% when 'product' %}
   {% if product.type == link.title %}
      <li id="current">{{ link.title | link_to: link.url }}</li>
   {% else %}
      <li>{{ link.title | link_to: link.url }}</li>
   {% endif %}
{% else %}
    <li>{{ link.title | link_to: link.url }}</li>
{% endcase%}
{% endfor %}

This is obviously very restrictive and will not server as a general solution.

What may be useful is to add a concept of a navigationContext attribute to product, collection, and navigation link which would make it very easy to then check the navigationContext of the current collection or product against the current navigation link selected. This would still result in the verbose block of code but it would remove the need to match product types with collection titles and link titles.

FYI, my name is changed because I must have mistyped my email address when I created my account so I am not able to log in using my full name :-(

0 Likes
New Member
19 0 0

I was looking for a way to do this just for collections. I was searching for something that would allow me to use regular expressions, but this solution takes care of highlighting a navigation menu link when you are in the product (which a regular expression would never work for). The only problem is that you have to follow naming conventions so that the product type matches the name of the link, which may require shuffling product types a bit.

In any regards, it seems like this might work for me. Thanks!

0 Likes
New Member
2 0 0

Thank you for the solution, this did it for me!

0 Likes