How to build collapsible sidebars with Bootstrap and jQuery

In this tutorial we will use the Bootstrap 3 grid system and some CSS and jQuery to create three separate solutions:

This approach works with both fixed and fluid containers.

Collapsible left sidebar

Bootstrap 3 has a responsive grid system with 12 columns. Our sidebar will occupy 3 columns and the remaining 9 columns will be used for the content.

It’s important to know this as it will influence the implementation. You should adapt the solution to your desired size.

<div class="container">
    <div class="row" id="row-main">
        <div class="col-md-3" id="sidebar">
            ...
        </div>
        <div class="col-md-9" id="content">
            ...
        </div>
    </div>
</div>

The following will happen when collapsing the sidebar:

  • The sidebar will be hidden
  • The content container will occupy the space left available by the sidebar

In our case the content container will go from occupying 9 columns to occupying all 12.

Another consideration is how the sidebar will be hidden. We’ll implement it in two ways:

  • For large displays we’ll use a negative left margin (with the same width as the sidebar) so we can animate the transition
  • For small displays, since each column is broken into its own line, we’ll just hide the sidebar when collapsed
.collapsed {
    display: none; /* hide it for small displays */
}
@media (min-width: 992px) {
    .collapsed {
        display: block;
        margin-left: -25%; /* same width as sidebar */
    }
}

Notice the media query breakpoint. We are using the appropriate min-width breakpoint for medium-sized columns (.col-md-). You need to adapt this if you are using columns of a different size.

Since we are assigning a negative left margin, the sidebar will be pushed off the container. We need to hide it. We do that by setting the overflow on the main row.

#row-main {
    overflow-x: hidden; /* necessary to hide collapsed sidebar */
}

Now the only thing left to do is to handle the animation.

#content {
    -webkit-transition: width 0.3s ease;
    -moz-transition: width 0.3s ease;
    -o-transition: width 0.3s ease;
    transition: width 0.3s ease;
}
#sidebar {
    -webkit-transition: margin 0.3s ease;
    -moz-transition: margin 0.3s ease;
    -o-transition: margin 0.3s ease;
    transition: margin 0.3s ease;
}

And when we want to toggle the sidebar, we just switch the appropriate CSS classes:

$("#sidebar").toggleClass("collapsed");
$("#content").toggleClass("col-md-12 col-md-9");

Collapsible right sidebar

As you can imagine, having the sidebar on the right doesn’t require a very different solution.

The HTML will have a small adjustment – the sidebar will appear after the content container.

<div class="container">
    <div class="row" id="row-main">
        <div class="col-md-9" id="content">
            ...
        </div>
        <div class="col-md-3" id="sidebar">
            ...
        </div>
    </div>
</div>

The only other thing that changes in the solution is that the margin will be applied to the right side:

@media (min-width: 992px) {
    .collapsed {
        display: block;
        margin-right: -25%; /* same width as sidebar */
    }
}

The rest will remain the same.

Collapsible sidebar on both sides

Having sidebars on both sides makes the solution just a little bit trickier.

The HTML structure now includes two sidebars.

<div class="container">
    <div class="row" id="row-main">
        <div class="col-md-3 sidebar" id="sidebar-left">
            ...
        </div>
        <div class="col-md-6" id="content">
            ...
        </div>
        <div class="col-md-3 sidebar" id="sidebar-right">
            ...
        </div>
    </div>
</div>

We accommodate the CSS to take into account the different collapsed states.

@media (min-width: 992px) {
    .collapsed {
        display: block;
    }
    #sidebar-left.collapsed {
        margin-left: -25%; /* same width as sidebar */
    }
    #sidebar-right.collapsed {
        margin-right: -25%; /* same width as sidebar */
    }
}

Since both sidebars now share a common class, we also need to update the transition code.

.sidebar {
    -webkit-transition: margin 0.3s ease;
    -moz-transition: margin 0.3s ease;
    -o-transition: margin 0.3s ease;
    transition: margin 0.3s ease;
}

On the Javascript side things get more complicated since now we have to consider 3 different widths for the content container.

To collapse or expand a sidebar we need to:

  • Toggle the collapsed class on the sidebar
  • Find the number of open sidebars
  • Determine the appropriate content class according to the number of open sidebars
  • Apply the correct class to the content container

The content container will switch between 6, 9, or 12 columns, since each sidebar occupies 3 columns exactly.

function toggleSidebar(side) {
    if (side !== "left" && side !== "right") {
        return false;
    }
    var left = $("#sidebar-left"),
        right = $("#sidebar-right"),
        content = $("#content"),
        openSidebarsCount = 0,
        contentClass = "";
    
    // toggle sidebar
    if (side === "left") {
        left.toggleClass("collapsed");
    } else if (side === "right") {
        right.toggleClass("collapsed");
    }
    
    // determine number of open sidebars
    if (!left.hasClass("collapsed")) {
        openSidebarsCount += 1;
    }
    
    if (!right.hasClass("collapsed")) {
        openSidebarsCount += 1;
    }
    
    // determine appropriate content class
    if (openSidebarsCount === 0) {
        contentClass = "col-md-12";
    } else if (openSidebarsCount === 1) {
        contentClass = "col-md-9";
    } else {
        contentClass = "col-md-6";
    }
    
    // apply class to content
    content.removeClass("col-md-12 col-md-9 col-md-6")
        .addClass(contentClass);
}

We can toggle the sidebar by calling the above function with the appropriate parameter.

toggleSidebar("left");

Conclusion

With Bootstrap 3, jQuery and some CSS magic we built a collapsible sidebar with expandable content.

You can find the source code at GitHub or in the 3 examples:

Nuno Freitas
Posted by Nuno Freitas on August 24, 2015

Related articles