<div id="my-sidebar-context" class="widget-sidebar-context">
    <header id="this-header" class="navbar justify-content-start navbar-dark bg-dark page-header">

        <a class="navbar-brand" href="example-link">
            Fixed Sidebar example
        </a>


        <a href="example-link" class="navbar-toggler widget-sidebar-toggler">
            <i class="fas fa-bars"></i>
        </a>
    </header>
    <div class="page-body">
        <nav class="widget-sidebar">
            <ul class="list-unstyled mt-2">
                <li class="active">
                    <a href="example-link">
                        <i class="fas fa-bars"></i><span> Dashboard </span>
                    </a>
                </li>
                <li>
                    <a href="example-link">
                        <i class="fas fa-pencil-alt"></i><span> Typography </span>
                    </a>
                </li>
                <li>
                    <a href="#sidebar-link-mycomponents" data-toggle="collapse"
                       aria-expanded="true"
                       class="dropdown-toggle">
                        <i class="fas fa-shapes"></i><span> Components </span>
                    </a>
                    <ul class="collapse list-unstyled show"
                        id="sidebar-link-mycomponents">
                        <li>
                            <a href="example-link">Alerts</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </nav>


        <div class="page-main">
            <h1>Main Content</h1>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto, placeat.</p>
        </div>
    </div>
    <footer class="page-footer bg-dark text-white p-3">
        <div>
            <span>My Footer © 2019</span>
        </div>
    </footer>
</div>
/*------------------------------------
- META VARIABLES
------------------------------------*/
$header_height: 50px;
$break_point_sm: 576px;
$break_point_md: 768px;
$break_point_lg: 992px;
$break_point_xl: 1200px;


/*------------------------------------
- SIDEBAR VARIABLES
------------------------------------*/
$sidebar_breakpoint: $break_point_lg;
$sidebar_width: 240px;
$sidebar_bg_color: #262D33;
$sidebar_active_ul_bg_color: #315472;
$sidebar_active_ul_color: #fff;
$sidebar_active_li_bg_color: #072433;
$sidebar_link_hover_bg_color: #414d58;
$sidebar_link_color: #e0e0e0;
$sidebar_link_indent_one: 30px;
$sidebar_link_indent_two: 50px;
$sidebar_border_left_color: #608ab3;
$transition_speed: 0.24s;


.widget-sidebar-context {
  position: relative;

  /**
  make the footer go at the bottom of the screen
   */
  display: flex;
  flex-direction: column;
  min-height: 100vh;


  .page-header {
    position: relative;
    z-index: 1025;
  }

  .page-body {
    background: #e3e3e3;
    flex-grow: 1;
    display: flex;


    .widget-sidebar {
      position: fixed;
      width: $sidebar_width;
      height: calc(100vh - #{$header_height});

      /**
      Note: we use margin-left instead of transform: translateX because it seems that the latter
      extends the width of the divs, which makes scrollbars appear in certain cases,
      while on the other hand with margin-left the content remains constrained inside its container div boundaries.
       */
      margin-left: -$sidebar_width;

      z-index: 1024;

      display: flex;
      display: -ms-flexbox;
      flex-direction: column;
      padding: 0;
      color: #fff;
      background: $sidebar_bg_color;
      transition: margin $transition_speed, opacity $transition_speed;
      overflow-y: auto;
      opacity: 0;


      i {
        margin-right: 7px;
      }

      a[data-toggle="collapse"] {
        position: relative;
      }

      .dropdown-toggle::after {
        display: block;
        position: absolute;
        top: 50%;
        right: 20px;
        transform: translateY(-50%);
      }


      [aria-expanded="false"]::after {
        transition: transform $transition_speed;
        transform: rotate(-90deg);

      }

      [aria-expanded="true"]::after {
        transition: transform $transition_speed;
        transform: rotate(0deg);

      }

      a[aria-expanded="true"], a.active {
        color: $sidebar_active_ul_color;
        background: $sidebar_active_ul_bg_color;
      }


      ul li a {
        padding: 10px;
        font-size: 1em;
        display: block;
        color: $sidebar_link_color;
        text-decoration: none;
        border-left: 2px solid transparent;

      }

      ul li a:hover {
        background: $sidebar_link_hover_bg_color;
        border-left: 2px solid $sidebar_border_left_color;
      }


      ul ul a {
        font-size: 0.9em !important;
        padding-left: $sidebar_link_indent_one !important;
      }

      ul ul ul a {
        padding-left: $sidebar_link_indent_two !important;
      }

      .active {
        background-color: $sidebar_active_li_bg_color;
      }


      /*------------------------------------
      - NATURAL RESPONSIVENESS for the sidebar
      ------------------------------------*/
      @media (min-width: $sidebar_breakpoint) {
        margin-left: 0px;
        opacity: 1;

      }

    }
  }


  .page-main{
    margin-left: 0;

    flex: 1;
    /**
    * Very important!!
    * Without it, the reponsive tables (.table-responsive) class won't work properly inside cards.
    * Spent 1 hour to find it...
    */
    min-width: 0;
  }

  .page-main, .page-footer{
    @media (min-width: $sidebar_breakpoint) {
      margin-left: $sidebar_width;
    }
  }


    /*------------------------------------
    - CLICKED STATES
    ------------------------------------*/
  &.sidebar-show {
    .widget-sidebar {
      margin-left: 0px;
      opacity: 1;
    }

    .page-main, .page-footer {
      margin-left: $sidebar_width;
    }

    @media (max-width: $break_point_sm) {

      .page-main::before {
        position: fixed;
        top: 0;
        left: 0;
        z-index: 1010;
        width: 100%;
        height: 100%;
        content: "";
        background: rgba(0, 0, 0, .7);
        animation: opacity .25s;
      }
    }
  }

  &.sidebar-hide {
    .widget-sidebar {
      margin-left: -$sidebar_width;
      opacity: 0;
    }

    .page-main, .page-footer {
      margin-left: 0;
    }
  }


}
document.addEventListener('DOMContentLoaded', (event) => {
    $('#my-sidebar-context').simpleSidebar();
});

The html architecture

First, we need to create the html structure. The html structure is composed of a wrapper (called context) containing all elements pertaining to the sidebar widget.

Those elements are:

  • a header (.page-header) containing the sidebar toggler (which toggles the sidebar on/off)
  • a body (.page-body)
  • a footer (.page-footer)

The sidebar itself is contained in the body, which contains the following elements:

  • the sidebar (.widget-sidebar)
  • the main content (.page-main)

How does the sidebar behave?

The sidebar has a default behaviour.
By default, the sidebar is responsive, and so it reacts to a break point automatically: it basically disappears on small screens, and re-appears on large screens.
However, once you've click on the sidebar toggler button (in the header), you switch to a manual mode, where the sidebar toggles only when you click that toggler button (i.e. it doesn't respond to break points anymore).
In short, you are in automatic mode until you click the toggler button, which then switches you to the manual mode until you refresh the page again.

The dynamic markup

In this section we list the important html markup which makes the sidebar alive.

The active state

By default, all sidebar items have the same style. To emphasize that a sidebar item is active (selected), we add the .active class to it (to the li element).

Parent/Children relationship

The sidebar items are like leaves of a tree, some of them contain children, some other don't.
To create a parent, we need to add an a tag inside the li item, and this a tag contains another ul containing the children items. On the a tag of the parent node, we need to add the following markup:

  • href: #$target (you choose $target arbitrarily)
  • data-toggle: collapse
  • aria-expanded: true|false (either true or false)
  • class: dropdown-toggle

And then on the ul tag of the parent element, add the following:

  • class: collapse
  • class: show (if you want to display the children)
  • id: $target

My Footer

Tool box