Elegant themes are giving away thousands of free prizes from the Divi and WordPress communities. I don't want to miss it! Ad

Bootstrap Sidebar

Published: 25.4.2018 | Last update: 19.6.2018

Today I’d like to show you how to create a collapsible HTML sidebar navigation using Bootstrap 4 with some CSS and jQuery.

Since Bootstrap 4 nor Bootstrap 3 don't provide one, we will build 5 separate solutions, each of them with slightly different features. In each part of the tutorial, I will guide you step by step through all the necessary steps in HTML, CSS and JavaScript.

Bootstrap Sidebar

We're going to build 5 sidebars like this one.

Here is what we're going to build:

Download Sources

Demo #1 Demo #2 Demo #3 Demo #4 Demo - Bonus section

Originally, I published this tutorial for Bootstrap 3 in 2017.

Now, in 2018, I upgraded it to Bootstrap 4 and made some improvements based on your feedback. The Bootstrap 3 version is a part of the download too, in case you would need it, though.

Basic files

Before we dig into coding, we should first set up our starting template with all the necessary files.

In all four cases, we'll go through today, we will need Bootstrap 4 CSS and JS files, jQuery library, and our custom stylesheet.

Also, I include Font Awesome 5 to be used on the buttons and menu items in one example.

So, our startup markup should be as following:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <title>Collapsible sidebar using Bootstrap 4</title>

    <!-- Bootstrap CSS CDN -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
    <!-- Our Custom CSS -->
    <link rel="stylesheet" href="style.css">

    <!-- Font Awesome JS -->
    <script defer src="https://use.fontawesome.com/releases/v5.0.13/js/solid.js" integrity="sha384-tzzSw1/Vo+0N5UhStP3bvwWPq+uvzCMfrN1fEFe+xBmv1C/AtVX5K0uZtmcHitFZ" crossorigin="anonymous"></script>
    <script defer src="https://use.fontawesome.com/releases/v5.0.13/js/fontawesome.js" integrity="sha384-6OIrr52G08NpOFSZdxxz1xdNSndlD4vdcf/q2myIUVO0VsqaGHJsB0RaBE01VTOY" crossorigin="anonymous"></script>
</head>

<body>


    <!-- jQuery CDN - Slim version (=without AJAX) -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <!-- Popper.JS -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
    <!-- Bootstrap JS -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>

</body>

</html>

Looking for a complete Bootstrap 4 template with a cool sidebar? Check out my Bootstrap 4 Dashboard or Bootstrap Material Admin.

1. Static collapsible sidebar menu

In this part, we are going to build a simple Bootstrap 4 sidebar that vertically scrolls along with the page. 

 

HTML

Basic document structure

We'll wrap everything in .wrapper box to make advantage of CSS flex property.

In this case, we'll give .wrapper the CSS property align-items: stretch.

By doing this, the sidebar will take the height of the page content. As the content increases, sidebar height dynamically increases.

<div class="wrapper">

    <!-- Sidebar -->
    <nav id="sidebar">
        ...
    </nav>

    <!-- Page Content -->
    <div id="content">
        <!-- We'll fill this with dummy content -->
    </div>

</div>       

Sidebar menu and its content

Now, let's fill our sidebar with some content.

I'll place there a sidebar navigation menu that will contain some demo navigation links and also some Bootstrap 4 drop-down menus.

Note, that we also added an .active class to the first item to mark that it is the current page. 

<div class="wrapper">
    <!-- Sidebar -->
    <nav id="sidebar">
        <div class="sidebar-header">
            <h3>Bootstrap Sidebar</h3>
        </div>

        <ul class="list-unstyled components">
            <p>Dummy Heading</p>
            <li class="active">
                <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Home</a>
                <ul class="collapse list-unstyled" id="homeSubmenu">
                    <li>
                        <a href="#">Home 1</a>
                    </li>
                    <li>
                        <a href="#">Home 2</a>
                    </li>
                    <li>
                        <a href="#">Home 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">About</a>
            </li>
            <li>
                <a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Pages</a>
                <ul class="collapse list-unstyled" id="pageSubmenu">
                    <li>
                        <a href="#">Page 1</a>
                    </li>
                    <li>
                        <a href="#">Page 2</a>
                    </li>
                    <li>
                        <a href="#">Page 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">Portfolio</a>
            </li>
            <li>
                <a href="#">Contact</a>
            </li>
        </ul>
    </nav>

</div>

Making dropdowns work

  1. To make a drop-down menu collapsible, data-toggle="collapse" should be added to the link holding the dropdown.
  2. Note that I also added class="dropdown-toggle" - this class adds that little triangle on the side and helps user understand that its function.
  3. The link's href attribute must contain the id of the dropdown menu preceded by a hash. In this case, I used #homeSubmenu for this approach.
  4. The dropdown menu itself also should have .collapse class too.
<a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Pages</a>
<ul class="collapse list-unstyled" id="pageSubmenu">
    <li>
        <a href="#">Page 1</a>
    </li>
    <li>
        <a href="#">Page 2</a>
    </li>
    <li>
        <a href="#">Page 3</a>
    </li>
</ul>

Be sure to add aria-expanded to the dropdown's control element <a>.

This attribute explicitly defines the current state of the collapsible element to screen readers and similar assistive technologies.

If the collapsible element is closed by default, it should have a value of aria-expanded="false". If you've set the collapsible element to be open by default using an .in class, set aria-expanded="true" on the control instead.

By clicking the anchor, the dropdown will slide up or slide down according to the aria-expanded="" value.

Sidebar toggle button

Now it's time to add the sidebar toggle button. This button will handle opening and closing of the sidebar.

We will place it outside the sidebar itself. It doesn't matter where it is located in your content as long as it's outside the sidebar, i.e. visible all the time.

Let's place it into the Bootstrap navbar in the content div.

<div id="content">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="container-fluid">

            <button type="button" id="sidebarCollapse" class="btn btn-info">
                <i class="fas fa-align-left"></i>
                <span>Toggle Sidebar</span>
            </button>

        </div>
    </nav>
</div>

CSS

Now it's time to finally apply some styling to our sidebar.

The most important thing for this approach is to use the flex property for the .wrapper div. As I mentioned above, stretch value will equalize both page content and sidebar height.

.wrapper {
    display: flex;
    width: 100%;
    align-items: stretch;
}

After that, we'll give the sidebar a fixed width of 250px.  

As a result of using flexbox properties, page content #content will take the remaining width of .wrapper. (as long as we don't use flex-wrap: wrap property) 

Then, we'll use sidebar's width to push the element out of the screen when we don't need it. This behaviour will be applied when the sidebar has an .active class.

Sorry I did not come up with some better class name when I wrote this tutorial in 2017.

On the desktops, #sidebar.active will mean that the sidebar is hidden and #sidebar only that it's visible.

It will have an opposite behaviour on mobiles where #sidebar.active is when the sidebar is visible and #sidebar is hidden.

.active class has a negative margin-left value that equals to the sidebar width.

We'll use this class later on in the JavaScript part, too.

.wrapper {
    display: flex;
    align-items: stretch;
}

#sidebar {
    min-width: 250px;
    max-width: 250px;
}

#sidebar.active {
    margin-left: -250px;
}

As we do not know if the content will vertically fill the entire screen, we will set the minimum height of the sidebar to 100vh. vh is a CSS unit that refers to the viewport height. 

This means that the initial height of the sidebar will be at least equal to the screen height. Also, its height will increase when the page content would increase.

#sidebar {
    min-width: 250px;
    max-width: 250px;
    min-height: 100vh;
}

Styling dropdowns

Just a little touch to the Bootstrap 4 drop-downs.

We are using standard Bootstrap 4 class .dropdown-toggle. This class adds a small triangle next to the drop-down links. To unify the links a bit, we will move the triangle, that usually sits next to the text, to the right part of the sidebar with the following CSS code.

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

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

Media query

We will need a slightly different behaviour for the sidebar on the smaller screens

Instead of appearing by default, it'll be hidden and appear only after clicking the toggle button. Like this, we will save valuable space for your content and show the navigation to the user only when needed.

Basically, what we need to do here is to reverse the .active style:

@media (max-width: 768px) {
    #sidebar {
        margin-left: -250px;
    }
    #sidebar.active {
        margin-left: 0;
    }
}

Additional styling

This would be all regarding the necessary CSS styling that is needed to make your sidebar work. 

To give it a more fancy look, I have styled it a bit more.

It is all included in the download package, so I will just quickly mention it here without any further comments.

/*
    ADDITIONAL DEMO STYLE, NOT IMPORTANT TO MAKE THINGS WORK BUT TO MAKE IT A BIT NICER :)
*/
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";


body {
    font-family: 'Poppins', sans-serif;
    background: #fafafa;
}

p {
    font-family: 'Poppins', sans-serif;
    font-size: 1.1em;
    font-weight: 300;
    line-height: 1.7em;
    color: #999;
}

a, a:hover, a:focus {
    color: inherit;
    text-decoration: none;
    transition: all 0.3s;
}

#sidebar {
    /* don't forget to add all the previously mentioned styles here too */
    background: #7386D5;
    color: #fff;
    transition: all 0.3s;
}

#sidebar .sidebar-header {
    padding: 20px;
    background: #6d7fcc;
}

#sidebar ul.components {
    padding: 20px 0;
    border-bottom: 1px solid #47748b;
}

#sidebar ul p {
    color: #fff;
    padding: 10px;
}

#sidebar ul li a {
    padding: 10px;
    font-size: 1.1em;
    display: block;
}
#sidebar ul li a:hover {
    color: #7386D5;
    background: #fff;
}

#sidebar ul li.active > a, a[aria-expanded="true"] {
    color: #fff;
    background: #6d7fcc;
}
ul ul a {
    font-size: 0.9em !important;
    padding-left: 30px !important;
    background: #6d7fcc;
}

JavaScript

The idea here is to toggle the .active class to the sidebar on clicking the toggle button.

By default, the sidebar will appear, i.e. it hasn't got .active class yet. 

After clicking the toggle button, the sidebar will be given an .active class, and pushed out from the screen. The page content will take the full-screen width too.

Re-clicking the toggle button will remove the .active class and the sidebar reappears again. And so on.

Let's have a look at the code:

$(document).ready(function () {

    $('#sidebarCollapse').on('click', function () {
        $('#sidebar').toggleClass('active');
    });

});

This completes our first example, let's have a look at what we've built.

View Demo

Get a web hosting + a free domain for just $1/mo - 100 GB storage, unmetered bandwidth and award-winning, 24/7 support from GoDaddy.

2. Fixed positioned scrollable sidebar

In this part, we'll make a similar sidebar but it will be fixed. This means that it won't scroll along with the page but it will stay fixed at the same place. This will apply only to larger devices with the width of 768px+.

HTML

This approach is similar to the previous sidebar navigation, therefore we can reuse the previous code.

Our markup should be as following:

<div class="wrapper">
    <!-- Sidebar -->
    <nav id="sidebar">
        <div class="sidebar-header">
            <h3>Bootstrap Sidebar</h3>
        </div>

        <ul class="list-unstyled components">
            <p>Dummy Heading</p>
            <li class="active">
                <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Home</a>
                <ul class="collapse list-unstyled" id="homeSubmenu">
                    <li>
                        <a href="#">Home 1</a>
                    </li>
                    <li>
                        <a href="#">Home 2</a>
                    </li>
                    <li>
                        <a href="#">Home 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">About</a>
            </li>
            <li>
                <a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Pages</a>
                <ul class="collapse list-unstyled" id="pageSubmenu">
                    <li>
                        <a href="#">Page 1</a>
                    </li>
                    <li>
                        <a href="#">Page 2</a>
                    </li>
                    <li>
                        <a href="#">Page 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">Portfolio</a>
            </li>
            <li>
                <a href="#">Contact</a>
            </li>
        </ul>

    </nav>
    <!-- Page Content -->
    <div id="content">

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="container-fluid">

                <button type="button" id="sidebarCollapse" class="btn btn-info">
                    <i class="fas fa-align-left"></i>
                    <span>Toggle Sidebar</span>
                </button>
            </div>
        </nav>
    </div>
</div>

CSS

As we need a fixed height sidebar, we'll get rid of align-items property that stretched items vertically.

However the content extends, the sidebar still will take entire viewport height. For this, we'll replace min-height: 100vh with height: 100vh

.wrapper {
    display: flex;
    width: 100%;
}

#sidebar {
    width: 250px;
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    z-index: 999;
    background: #7386D5;
    color: #fff;
    transition: all 0.3s;
}

At this point, we've finished all the CSS modifications.

We'll add two extra tricks in the JavaScript, let's have a look at them now.

JavaScript

The first trick is that I'll replace the default browser scrollbar in the side menu with a custom one. We will need the scrollbar there just in case navbar would be too high to fit in the viewport.

For this purpose, I'll use jQuery custom content scroller. Let's first add its JS file to our HTML file.

    <!-- jQuery CDN - Slim version (=without AJAX) -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <!-- Popper.JS -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
    <!-- Bootstrap JS -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
    <!-- jQuery Custom Scroller CDN -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.concat.min.js"></script>

</body>
</html>

And its stylesheet file to the <head> element:

<!-- Our Custom CSS -->
<link rel="stylesheet" href="style2.css">
<!-- Scrollbar Custom CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.min.css">

Now, let's initialize the plugin and use some of its options

$(document).ready(function () {

    $("#sidebar").mCustomScrollbar({
         theme: "minimal"
    });

    $('#sidebarCollapse').on('click', function () {
        $('#sidebar').toggleClass('active');
    });

});

The second trick, I'll make the open dropdowns to be closed while the sidebar is collapsed out. The reason for this is to keep things consistent and to open a navbar with closed dropdowns every time.

$(document).ready(function () {

    $("#sidebar").mCustomScrollbar({
         theme: "minimal"
    });

    $('#sidebarCollapse').on('click', function () {
        // open or close navbar
        $('#sidebar').toggleClass('active');
        // close dropdowns
        $('.collapse.in').toggleClass('in');
        // and also adjust aria-expanded attributes we use for the open/closed arrows
        // in our CSS
        $('a[aria-expanded=true]').attr('aria-expanded', 'false');
    });

});

To clarify what we have done here. The class .in is responsible for opening the dropdown menu. If it has one, it's open, if not, it's closed. We told our JavaScript that if this class is present, please remove it. Also, please change the aria-expanded value from true to false so the arrow will return to its logical direction.

This makes our fixed sidebar navigation complete. Let's have a look at what we've built.

View Demo

3. Fixed scrollable sidebar menu with a content overlay

In this approach, we'll make a side navbar similar to the one that Google uses for their navbars on tablets and mobile phones in Material design

The sidebar will cover the left part of the page content when it's open and the rest of the content will be covered by a dark transparent overlay.

HTML

We'll use the same markup above and add a #dismiss button to the sidebar. This button will be responsible for the closing of the sidebar when it's open.

And since we'll apply a transparent overlay, let's insert an .overlay div at the very bottom of our page for that purpose too.

<div class="wrapper">
    <!-- Sidebar -->
    <nav id="sidebar">

        <div id="dismiss">
            <i class="fas fa-arrow-left"></i>
        </div>

        <div class="sidebar-header">
            <h3>Bootstrap Sidebar</h3>
        </div>

        <ul class="list-unstyled components">
            <p>Dummy Heading</p>
            <li class="active">
                <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false">Home</a>
                <ul class="collapse list-unstyled" id="homeSubmenu">
                    <li>
                        <a href="#">Home 1</a>
                    </li>
                    <li>
                        <a href="#">Home 2</a>
                    </li>
                    <li>
                        <a href="#">Home 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">About</a>
                <a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false">Pages</a>
                <ul class="collapse list-unstyled" id="pageSubmenu">
                    <li>
                        <a href="#">Page 1</a>
                    </li>
                    <li>
                        <a href="#">Page 2</a>
                    </li>
                    <li>
                        <a href="#">Page 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">Portfolio</a>
            </li>
            <li>
                <a href="#">Contact</a>
            </li>
        </ul>
    </nav>

    <!-- Page Content -->
    <div id="content">

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="container-fluid">

                <button type="button" id="sidebarCollapse" class="btn btn-info">
                    <i class="fas fa-align-left"></i>
                    <span>Toggle Sidebar</span>
                </button>
            </div>
        </nav>
    </div>
    <!-- Dark Overlay element -->
    <div class="overlay"></div>
</div>

CSS

The sidebar will have a fixed positioning at the left part of the screen and content will take the full screen all the time.

By default, the sidebar will be hidden. When the toggle button is clicked, both .overlay and the sidebar will appear above the content.

Let's imagine it as layers, the page content will be the back layer, .overlay will be the middle layer with a transparent black colour. The overlay will cover the content of the page to allow user's eye easily focus on the sidebar itself. Finally, the sidebar will be the front layer.

To achieve this layering behaviour, we will simply use z-index property.

As mentioned before, we will be also adding a  #dismiss button to the sidebar. It will be positioned absolutely at its top right part.

.wrapper {
    display: block;
}

#sidebar {
    min-width: 250px;
    max-width: 250px;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    /* top layer */
    z-index: 9999;
}

.overlay {
    display: none;
    position: fixed;
    /* full screen */
    width: 100vw;
    height: 100vh;
    /* transparent black */
    background: rgba(0, 0, 0, 0.7);
    /* middle layer, i.e. appears below the sidebar */
    z-index: 998;
    opacity: 0;
    /* animate the transition */
    transition: all 0.5s ease-in-out;
}
/* display .overlay when it has the .active class */
.overlay.active {
    display: block;
    opacity: 1;
}

#dismiss {
    width: 35px;
    height: 35px;
    position: absolute;
    /* top right corner of the sidebar */
    top: 10px;
    right: 10px;
}

JavaScript

In two previous sidebars, the toggle button functionality was to open/close the sidebar. Here, we already have a close button inserted in our sidebar, so the toggle button function is only to open the sidebar.

To clarify the mechanism, by clicking the toggle button both overlay and sidebar appear, and by clicking the sidebar close button, both overlay and sidebar disappear.

 

<script type="text/javascript">
    $(document).ready(function () {
        $("#sidebar").mCustomScrollbar({
            theme: "minimal"
        });

        $('#dismiss, .overlay').on('click', function () {
            // hide sidebar
            $('#sidebar').removeClass('active');
            // hide overlay
            $('.overlay').removeClass('active');
        });

        $('#sidebarCollapse').on('click', function () {
            // open sidebar
            $('#sidebar').addClass('active');
            // fade in the overlay
            $('.overlay').addClass('active');
            $('.collapse.in').toggleClass('in');
            $('a[aria-expanded=true]').attr('aria-expanded', 'false');
        });
    });
</script>

This is it. Time to check the demo.

View Demo

4. Partially collapsing static sidebar

In this example, we will, instead of building a sidebar that collapses entirely, build a Partially collapsing side navbar. The side menu will convert itself into a compressed version after the toggle button click.

Let's use the first approach's markup as a starting point.

HTML

To further enhance it, we will insert an icon into the navigation links.

We will use Font Awesome for the icons in the side menu. 

<div class="wrapper">
    <!-- Sidebar  -->
    <nav id="sidebar">
        <div class="sidebar-header">
            <h3>Bootstrap Sidebar</h3>
            <strong>BS</strong>
        </div>

        <ul class="list-unstyled components">
            <li class="active">
                <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
                    <i class="fas fa-home"></i>
                    Home
                </a>
                <ul class="collapse list-unstyled" id="homeSubmenu">
                    <li>
                        <a href="#">Home 1</a>
                    </li>
                    <li>
                        <a href="#">Home 2</a>
                    </li>
                    <li>
                        <a href="#">Home 3</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">
                    <i class="fas fa-briefcase"></i>
                    About
                </a>
                <a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
                    <i class="fas fa-copy"></i>
                    Pages
                </a>
                <ul class="collapse list-unstyled" id="pageSubmenu">
                    <li>
                        <a href="#">Page 1</a>
                    </li>
                    <li>
                        <a href="#">Page 2</a>
                    </li>
                    <li>
                        <a href="#">Page 3</a>
                    </li>
                </ul>
            </li>
        </ul>

    </nav>

    <!-- Page Content  -->
    <div id="content">

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="container-fluid">

                <button type="button" id="sidebarCollapse" class="btn btn-info">
                    <i class="fas fa-align-left"></i>
                    <span>Toggle Sidebar</span>
                </button>
            </div>
        </nav>
    </div>
</div>

CSS

Instead of pushing the sidebar entirely out of the screen, we'll just shrink its width, and restyle its content to fit this new width. The styles of the compressed version will be added to the class .active

For example, we will downsize the font size of the anchors' text, align it to centre and make it render below the icon. Also, we will move the arrow to the very bottom of every anchor, or adjust the padding around the dropdown links.

The code will be as follows:

/* Shrinking the sidebar from 250px to 80px and center aligining its content*/
#sidebar.active {
    min-width: 80px;
    max-width: 80px;
    text-align: center;
}

/* Toggling the sidebar header content, hide the big heading [h3] and showing the small heading [strong] and vice versa*/
#sidebar .sidebar-header strong {
    display: none;
}
#sidebar.active .sidebar-header h3 {
    display: none;
}
#sidebar.active .sidebar-header strong {
    display: block;
}

#sidebar ul li a {
    text-align: left;
}

#sidebar.active ul li a {
    padding: 20px 10px;
    text-align: center;
    font-size: 0.85em;
}

#sidebar.active ul li a i {
    margin-right:  0;
    display: block;
    font-size: 1.8em;
    margin-bottom: 5px;
}

/* Same dropdown links padding*/
#sidebar.active ul ul a {
    padding: 10px !important;
}

/* Changing the arrow position to bottom center position, 
   translateX(50%) works with right: 50% 
   to accurately  center the arrow */
#sidebar.active .dropdown-toggle::after {
    top: auto;
    bottom: 10px;
    right: 50%;
    -webkit-transform: translateX(50%);
    -ms-transform: translateX(50%);
    transform: translateX(50%);
}

Media queries

On smaller screens, we'll keep the compressed version as a default active state of the sidebar. I.e., the uncompressed version will not be used on mobiles at all and the compressed version will become visible after clicking the toggle button.

To achieve this, we can only copy the styles from .active to our  mobile media query @media (max-width: 768px)  and add a margin-left functionality to it.

For mobiles, #sidebar.active sidebar will have a negative left margin (it will be off the canvas) and the #sidebar without the .active class will have margin-left set to 0.

@media (max-width: 768px) {
    /* 80px and its content aligned to centre. Pushing it off the screen with the
       negative left margin
    */
    #sidebar.active {
        min-width: 80px;
        max-width: 80px;
        text-align: center;
        margin-left: -80px !important;
    }


    /* Reappearing the sidebar on toggle button click */
    #sidebar {
        margin-left: 0; 
    }


    /* Toggling the sidebar header content, 
       hide the big heading [h3] and showing the small heading [strong] and vice versa
    */
    #sidebar .sidebar-header strong {
        display: none;
    }
    #sidebar.active .sidebar-header h3 {
        display: none;
    }
    #sidebar.active .sidebar-header strong {
        display: block;
    }

    /* Downsize the navigation links font size */
    #sidebar.active ul li a {
        padding: 20px 10px;
        font-size: 0.85em;
    }

    #sidebar.active ul li a i {
        margin-right:  0;
        display: block;
        font-size: 1.8em;
        margin-bottom: 5px;
    }

    /* Adjust the dropdown links padding*/
    #sidebar.active ul ul a {
        padding: 10px !important;
    }

    /* Changing the arrow position to bottom center position, 
      translateX(50%) works with right: 50% 
      to accurately  center the arrow */
    .dropdown-toggle::after {
        top: auto;
        bottom: 10px;
        right: 50%;
        -webkit-transform: translateX(50%);
        -ms-transform: translateX(50%);
        transform: translateX(50%);
    }
}

JavaScript

We will not include any additional lines of JavaScript and we'll just use the same function did use in the first sidebar.

$(document).ready(function () {

    $('#sidebarCollapse').on('click', function () {
        $('#sidebar').toggleClass('active');
    });

});

That will be all for now. We should have a nicely working partially collapsing sidebar.

Let's have a look at the results.

View Demo

Further Improvements

There is always room for some further improvements and tweaks.

As a bonus, I would like to show you how to prepare an animated hamburger menu icon for the toggle button, and also how to add eye-catching animation for the opening and closing of the sidebar panel.

HTML

Again, I will use the simple sidebar from the first example as a base.

But instead of using a Glyphicon for the toggle button, let's place three spans there instead. Each one will represent a bar of the hamburger menu and we will style them with CSS later on.

<div class="wrapper">

        <nav id="sidebar">
            <!-- Sidebar Header -->
            <div class="sidebar-header">
                <h3>Collapsible Sidebar</div>
            </div>

            <!-- Sidebar Links -->
            <ul class="list-unstyled components">
                <li class="active"><a href="#">Home</a></li>
                <li><a href="#">About</a></li>
                <li><!-- Link with dropdown items -->
                    <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false">Pages</a>
                    <ul class="collapse list-unstyled" id="homeSubmenu">
                        <li><a href="#">Page</a></li>
                        <li><a href="#">Page</a></li>
                        <li><a href="#">Page</a></li>
                    </ul>
                <li><a href="#">Portfolio</a></li>
                <li><a href="#">Contact</a></li>
            </ul>
        </nav>

        <div id="content">
            <button type="button" id="sidebarCollapse" class="navbar-btn">
                <span></span>
                <span></span>
                <span></span>
            </button>
        <div>

</div>

CSS

Animating the toggle button

Let's add some styles to the button and its bars first.

There'll be three bars under each other and we'll give them a fancy transition with a cubic-bezier transition. I often use this CSS animation tool to produce cool transitions, you can choose from some pre-build transitions or make your custom one easily.

 #sidebarCollapse {
    width: 40px;
    height: 40px;
    background: #f5f5f5;
}

#sidebarCollapse span {
    width: 80%;
    height: 2px;
    margin: 0 auto;
    display: block;
    background: #555;
    transition: all 0.8s cubic-bezier(0.810, -0.330, 0.345, 1.375);
}

When the sidebar is open, the toggle button bars will be crossed. When it's off the canvas, the bars will be parallel to each other.

By default, the sidebar will be open, so the initial state of the bars should be crossed. We'll use transform property to achieve that. The first bar will be rotated by 45 degrees, the last bar will be rotated by 45 degrees in the opposite direction. The second bar will be hidden in this moment.

#sidebarCollapse span:first-of-type {
    /* rotate first one */
    transform: rotate(45deg) translate(2px, 2px);
}
#sidebarCollapse span:nth-of-type(2) {
    /* second one is not visible */
    opacity: 0;
}
#sidebarCollapse span:last-of-type {
    /* rotate third one */
    transform: rotate(-45deg) translate(1px, -1px);
}

By clicking the button, the bars turn into the parallel state. To make that, we will use jQuery to toggle .active class on the button. This class cancels the rotation of the bars and makes them all visible.

#sidebarCollapse.active span {
    /* no rotation */
    transform: none;
    /* all bars are visible */
    opacity: 1;
    margin: 5px auto;
}

Animating the sidebar

Now, let's add some 3D CSS animation to the sidebar.

We'll make a door-opening animation when the user closes or opens the sidebar.

First of all, we should add perspective property to the container. Our container in this case is .wrapper. The perspective property defines how many pixels a 3D element is placed from the view and allows you to change the perspective on how 3D elements are viewed.

Then, we'll rotate the sidebar vertically by 100 degrees during collapsing out using transform property.

The transform-origin property allows you to change the position of transformed elements. Here we'll rotate the sidebar from the center left side.

.wrapper {
    display: flex;
    align-items: stretch;
    perspective: 1500px; 
}

#sidebar {
    min-width: 250px;
    max-width: 250px;
    background: #7386D5;
    color: #fff;
    transition: all 0.6s cubic-bezier(0.945, 0.020, 0.270, 0.665);
    transform-origin: center left; /* Set the transformed position of sidebar to center left side. */
}

#sidebar.active {
    margin-left: -250px;
    transform: rotateY(100deg); /* Rotate sidebar vertically by 100 degrees. */
}

Media Queries

On smaller screens, the sidebar will be collapsed out by default. The default state of the hamburger menu should be returned to the parallel state. To achieve this, we should switch the CSS rules from  the standard view.

@media (max-width: 768px) {
    /* Reversing the behavior of the sidebar: 
       it'll be rotated vertically and off canvas by default, 
       collapsing in on toggle button click with removal of 
       the vertical rotation.   */
    #sidebar {
        margin-left: -250px;
        transform: rotateY(100deg);
    }
    #sidebar.active {
        margin-left: 0;
        transform: none;
    }

    /* Reversing the behavior of the bars: 
       Removing the rotation from the first,
       last bars and reappear the second bar on default state, 
       and giving them a vertical margin */
    #sidebarCollapse span:first-of-type,
    #sidebarCollapse span:nth-of-type(2),
    #sidebarCollapse span:last-of-type {
        transform: none;
        opacity: 1;
        margin: 5px auto;
    }

    /* Removing the vertical margin and make the first and last bars rotate again when the sidebar is open, hiding the second bar */
    #sidebarCollapse.active span {
        margin: 0 auto;
    }
    #sidebarCollapse.active span:first-of-type {
        transform: rotate(45deg) translate(2px, 2px);
    }
    #sidebarCollapse.active span:nth-of-type(2) {
        opacity: 0;
    }
    #sidebarCollapse.active span:last-of-type {
        transform: rotate(-45deg) translate(1px, -1px);
    }
}

Javascript

We'll use jQuery to toggle the .active class to switch between the crossed and parallel states.

$(document).ready(function () {
    $('#sidebarCollapse').on('click', function () {
        $('#sidebar').toggleClass('active');
        $(this).toggleClass('active');
    });
});

Let's have a look at the result.

View Demo

Conclusion

I hope this tutorial has helped you to understand how to implement a Bootstrap sidebar to your project. If you liked the article - let your friends know about it.

If you have enjoyed this Bootstrapious tutorial, have a look at my tutorials on How to build a contact form or Bootstrap navbar.

Thanks for reading :)

Hi, I'm Ondrej, creator of Bootstrapious. I have published Bootstrap tutorials and freebies here since 2015.

Thanks for stopping by and have a great day ;)

Ondrej, Bootstrapious

You might also like one of my Free Templates

Italiano - Restaurant or Café Template

Italiano is my free Bootstrap 4 HTML responsive template. You can use it to build an elegant…

View template

Foliou - Bootstrap Portfolio

Foliou is a responsive one-page Bootstrap 4 portfolio template. It presents your work in a…

View template

Bootstrap Blog

Bootstrap Blog is a free Bootstrap 4 blog template.  Its design is minimalistic, almost…

View template

Share on Facebook Share on G+ Share on Twitter Share on LinkedIn