Style Individual Top Nav Items

  1. TODO: provide method for child.slug = "donate"
  2. TODO: provide method for navfirst and navlast - what has to be done is provide a selector for last navigation item, and then remove the style that general applies to subnav but shouldn't apply to the last item (or in some cases the first)
  3. TODO: provide instructions on how to get selectors for each menu item: navitem1, navitem2, navitem3 etc
  4. TODO: explain benefit of storing the selectors in a variable that you print out via {{ navclasses }}
  5. TODO: is there a filter or a tag that adds a selector? if so that would be more elegant...
  6. TODO: answer question
  7. TODO: add headers to sections
  8. TODO: simplify the sections

To style a given navigation item it is convenient to have a unique selector for each list item of the top nav. By default NationBuilder provides those list items with classes dependent on if the item is active and if the item has children (ie is a dropdown). The relevant code is in the _nav.html template file.

For example, NationBuilder might output something like this (assuming the About page is active):

  1. <ul id="topnav">
  2. <li class="nodrop">
  3. <a href="/home">Home</a>
  4. </li>
  5. <li class="active">
  6. <a href="/about">About</a>
  7. </li>
  8. <li class="nodrop">
  9. <a href="/get_involved">Get Involved!</a>
  10. </li>
  11. <li class="nodrop">
  12. <a href="/donate">Donate</a>
  13. </li>
  14. </ul>

If we want the donate link to have a different background color than the other navigation items it might be useful to have additional selectors. If you really only cared about the donate page you could use an if then statement to add a class when child.slug = "donate." But if you're going to go to the trouble you may want to add selectors to the other items as well.

- - - Jerimee wants to simplify and rewrite below - - -

Another option is to use CSS child (>) and sibling (+) combinators to get what you want.

For instance say you want a list like the one below to be different colors:

  1. <ul>
  2. <li>foo</li>
  3. <li>bar</li>
  4. <li>zed</li>
  5. <li>fubar</li>
  6. </ul>

You could use four different selectors or you could just use combinators. Like so:

  1. ul>li {color:blue;}
  2. ul>li+li {color:red;}
  3. ul>li+li+li {color:green;}
  4. ul>li+li+li+li {color:orange;}

"ul>li" indicates any "child" lis with that ul, and "li+li" indicate any lis adjacent to any other li.

There is a tricky bit though. Say you wanted to just change "zed" to green in the example above. You might think that this would do it:

  1. ul>li+li+li {color:green;}

And it would. But it would also make "fubar" green as well. This is because children combinators refer to any child under a given element. This means that "ul>li" refers to all four list items above and therefore "ul>li+li+li" refers to both "zed" and "fubar" since "zed" is three adjacent from "foo" and "fubar" is three adjacent from "bar" and both "foo" and "bar" are children of the parent unordered list.

To counter this you'll have to either assign a class to "zed" and make that green instead or change "fubar" using "ul>li+li+li+li {color:black;}" because "ul>li+li+li+li" only refers to "fubar."

- - - Jerimee wants to simplify and rewrite above - - -

In _nav.html add "topnav_{{ | downcase }}" as a class to the relevant li. In my case: Then you'll be able to style each nav item separately with css. For example:  .topnav_donate { background-color: #FFFF00;}

Example code for _nav.html

  1. <div class="nav_container"><div class="navbg">
  2. <ul id="topnav">
  3. {% for child in site.root_nav_pages %}
  4. {% assign navclasses = 'navitem' %}{% if forloop.first %}{% capture navclasses %}{{ navclasses | append: ' navfirst'}}{% endcapture %}{% endif %}{% if forloop.last %}{% capture navclasses %}{{ navclasses | append: ' navlast'}}{% endcapture %}{% endif %}{% if child.is_or_is_ancestor_of_current_page? %}{% capture navclasses %}{{ navclasses | append: ' active'}}{% endcapture %}{% endif %}
  5. {% if child.leaf? or child.nav_children.size == 0 %}
  6. <li class="{{ navclasses | append: ' nodrop'}}">
  7. <a href="{{ child.url }}">{{ }}</a>
  8. </li>
  9. {% else %}
  10. <li class="{{ navclasses | append: ' drop'}}">
  11. <a href="{{ child.url }}">{{ }}</a>
  12. <div class="sub">
  13. <ul>
  14. {% if site.show_parent_in_nav_dropdown? %}
  15. <li><a href="{{ child.url }}">{{ }}</a></li>
  16. {% endif %}
  17. {% for child2 in child.nav_children %}
  18. <li><a href="{{ child2.url }}">{{ }}</a></li>
  19. {% endfor %}
  20. </ul>
  21. </div>
  22. </li>
  23. {% endif %}
  24. {% endfor %}
  25. </ul>
  26. </div>
  27. </div>
  28. <div style="clear: both;"></div>

Note the code that assigns selectors to each list item. The code below, along with adding selections for active menu item, first menu item, and last menu item, also add a selector based on the page slug.

  1. {% assign navclasses = 'mitem' %}
  2. {% capture pagesel %} miforpage_{{ mi.slug }}{% endcapture %}
  3. {% capture navclasses %}{{ navclasses | append: pagesel }}{% endcapture %}
  4. {% if mi.is_or_is_ancestor_of_current_page? %}{% capture navclasses %}{{ navclasses | append: ' miactive'}}{% endcapture %}{% endif %}
  5. {% if forloop.index == 1 %}{% capture navclasses %}{{ navclasses | append: ' mifirst'}}{% endcapture %}{% endif %}
  6. {% if forloop.last %}{% capture navclasses %}{{ navclasses | append: ' milast'}}{% endcapture %}{% endif %}
  7. <li class="{{navclasses}}">
  8. <!-- menu link goes here -->
  9. </li>