In 2020, we needed a sub-navigation system on jtcc.edu that matched up to the HTML that an outside company had built for us and it turned out to be a bit more complex than you might expect. We needed it to automatically show the direct children of any page a visitor visits. However, if the page does not have children, we needed it to show the siblings of the current page. If the page has grandchildren, we did not want those to show and if the page has a parent, we did not want that to show.
What made it complicated is the CMS we used, ExpressionEngine(EE) does not do this out-of-the-box. We used the Structure add-on to build the navigation on the site. However, it does not provide this specific functionality.
The below code would be output by EE/Structure but only the links within the span with the class of .children will show on the front-end of the site. In case you’re curious, the siblings spans are before and after the children span because the order they display is based on the order you have them in your Structure navigation for the entire site.
<ul> <span class="siblings"> <li class="sub_nav_item"> <a class="sub_nav_link not-current" href="/about/locations-tours/" ><span class="sub_nav_link_label">Locations</span ><span class="sub_nav_link_icon"> <svg class="icon icon_caret_right"> <use href="/images/icons.svg#caret_right"></use> </svg> </span> </a> </li> </span> <span class="children"> <li class="sub_nav_item"> <a class="sub_nav_link" href="/about/offices-and-divisions/institutional-effectiveness/" ><span class="sub_nav_link_label" >Office of Institutional Effectiveness</span ><span class="sub_nav_link_icon"> <svg class="icon icon_caret_right"> <use href="/images/icons.svg#caret_right"></use> </svg> </span> </a> </li> <li class="sub_nav_item"> <a class="sub_nav_link" href="/about/offices-and-divisions/dean-of-students/" ><span class="sub_nav_link_label">Dean of Students Office</span ><span class="sub_nav_link_icon"> <svg class="icon icon_caret_right"> <use href="/images/icons.svg#caret_right"></use> </svg> </span> </a> </li> </span> <span class="siblings"> <li class="sub_nav_item"> <a class="sub_nav_link not-current" href="/about/employment-opportunities/" ><span class="sub_nav_link_label">Employment Opportunities</span ><span class="sub_nav_link_icon"> <svg class="icon icon_caret_right"> <use href="/images/icons.svg#caret_right"></use> </svg> </span> </a> </li> </span> </ul>
After many attempts to do it with EE and Structure code, I finally decided to get the back-end code to output everything(the entire navigation from the root of the site to the current page and all of it’s children) and use front-end code to get it to only show what we wanted.
I used CSS to hide all the sibling links for a page if a page has children(.children ~ .siblings), all of the children links for a page if it has grand-children(.grand-children ~ .children), and lastly, all of the grand-children if a page has great grand-children(.great-grand-children ~ .grand-children).
.children ~ .siblings, .grand-children ~ .children, .great-grand-children ~ .grand-children{ display:none; }
The limit of CSS is that you can only affect elements after the current element you are calling. This is where JavaScript came in.
With a little bit of jQuery(which the site was already using in other places, so don’t come @ me JS Police!) I was able to hide all siblings if a page has grand-children and all siblings if a page has children.
<script> $(document).ready(function(){ $(".grand-children").prevAll(".siblings").css({"display": "none"}); $(".children").prevAll(".siblings").css({"display": "none"}); }); </script>
I hope you found this helpful. If so, please share it so other developers can keep it in mind when building out their websites and navigation systems!