Sidebar navigation

Sidebar navigation helps users navigate by displaying pages within a topic or section.

Best practices

  • Wherever possible, limit the number of parent navigation items to 10 and the children within a parent section to 15. If the side navigation is too long, users may miss items at the bottom. If there are too many levels, users may miss items that require too many clicks.
  • Parent items with children should always include a chevron. Parent items without children don’t require a chevron.
  • Only expand active subsections to emphasize which section the user is in and to reduce visual complexity.
  • Keep the navigation link text short.
  • Sidebar navigation should be displayed at the top of the sidebar on inner pages within the main City of Winnipeg site.

How it works

Add the class active to the active li and to the current page item. Use buttons with dropdown arrows to indicate any nav items that have children pages.

<nav aria-label="Sidebar navigation">
  <ul class="sidenav" role="menubar" aria-label="Sidebar navigation">
    <li>
      <button id="heading1" data-target="#collapse1" aria-expanded="false" aria-controls="collapse1" class="btn sidenav-item sidenav-btn sidebarBtn">Nav item with children<i class="far fa-chevron-down"></i></button>
      <ul id="collapse1" aria-labelledby="heading1">
        <li><a class="sidenav-item" href="#">Nav item</a></li>
        <li>
          <button id="heading2" data-target="#collapse2" aria-expanded="false" aria-controls="collapse2" class="btn sidenav-item sidenav-btn sidebarBtn">Nested item with children<i class="far fa-chevron-down"></i></button>
          <ul id="collapse2" aria-labelledby="heading2">
            <li><a class="sidenav-item" href="#">Child item</a></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
          </ul>
        </li>
        <li><a class="sidenav-item" href="#">Nav item</a></li>
      </ul>
    </li>
    <li class="active"><span class="sidenav-item active">Current page active</span></li>
    <li><a class="sidenav-item" href="#">Nav item without children</a></li>
  </ul>
</nav>


If the current active page is a child page, the dropdown menu should be expanded by default. Add the class show to the parent li and parent ul to show the menu, and active on the current page item for active styling.

<nav aria-label="Sidebar navigation">
  <ul class="sidenav" role="menubar" aria-label="Sidebar navigation">
    <li class="show">
      <button id="heading12" data-target="#collapse12" aria-expanded="true" aria-controls="collapse12" class="btn sidenav-item sidenav-btn sidebarBtn">Active parent<i class="far fa-chevron-up"></i></button>
      <ul class="show" id="collapse12" aria-labelledby="heading12">
        <li class="active"><span class="sidenav-item active">Current page active</span></li>
        <li>
          <button id="heading22" data-target="#collapse22" aria-expanded="false" aria-controls="collapse22" class="btn sidenav-item sidenav-btn sidebarBtn">Nested item with children<i class="far fa-chevron-down"></i></button>
          <ul id="collapse22" aria-labelledby="heading22">
            <li><a class="sidenav-item" href="#">Child item</a></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
          </ul>
        </li>
        <li><a class="sidenav-item" href="#">Nav item</a></li>
      </ul>
    </li>
    <li><a class="sidenav-item" href="#">Nav item without children</a></li>
    <li><a class="sidenav-item" href="#">Nav item without children</a></li>
  </ul>
</nav>


Up to three levels can be displayed.

<nav aria-label="Sidebar navigation">
  <ul class="sidenav" role="menubar" aria-label="Sidebar navigation">
    <li class="show">
      <button id="heading13" data-target="#collapse12" aria-expanded="true" aria-controls="collapse13" class="btn sidenav-item sidenav-btn sidebarBtn">Active parent<i class="far fa-chevron-up"></i></button>
      <ul class="show" id="collapse13" aria-labelledby="heading13">
        <li><a class="sidenav-item" href="#">Nav item</a></li>
        <li>
          <button id="heading23" data-target="#collapse22" aria-expanded="true" aria-controls="collapse23" class="btn sidenav-item sidenav-btn sidebarBtn">Second active parent<i class="far fa-chevron-up"></i></button>
          <ul class="show" id="collapse23" aria-labelledby="heading23">
            <li class="active"><span class="sidenav-item active">Current page active</span></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
            <li><a class="sidenav-item" href="#">Child item</a></li>
          </ul>
        </li>
        <li><a class="sidenav-item" href="#">Nav item</a></li>
      </ul>
    </li>
    <li><a class="sidenav-item" href="#">Nav item without children</a></li>
    <li><a class="sidenav-item" href="#">Nav item without children</a></li>
  </ul>
</nav>


Add the following JavaScript for the expand and collapse behaviour. Note that this code is also used for the vertical header and should not be added more then once.

$('.sidebarBtn').click(function() {
  $(this).find('i').toggleClass('fa-chevron-up fa-chevron-down');
  if($(this).attr('aria-expanded') == true){
    $(this).attr({'aria-expanded': false});
  }else{
    $(this).attr({'aria-expanded': true});
  }
  $(this).next('ul').slideToggle();
});

Accessibility

Be sure to add aria-expanded to the control element. This attribute explicitly conveys the current state of the collapsible element tied to the control to screen readers and similar assistive technologies. If the collapsible element is closed by default, the attribute on the control element should have a value of aria-expanded="false". If you’ve set the collapsible element to be open by default using the show class, set aria-expanded="true" on the control instead. The plugin will automatically toggle this attribute on the control based on whether or not the collapsible element has been opened or closed (via JavaScript, or because the user triggered another control element also tied to the same collapsible element). If the control element’s HTML element is not a button (e.g., an <a> or <div>), the attribute role="button" should be added to the element.

If your control element is targeting a single collapsible element – i.e. the data-target attribute is pointing to an id selector – you should add the aria-controls attribute to the control element, containing the id of the collapsible element. Modern screen readers and similar assistive technologies make use of this attribute to provide users with additional shortcuts to navigate directly to the collapsible element itself.

Note that Bootstrap’s current implementation does not cover the various keyboard interactions described in the WAI-ARIA Authoring Practices 1.1 accordion pattern - you will need to include these yourself with custom JavaScript.