Ravimallya
Ravimallya

Reputation: 6610

CSS3 animations when show hide bootstrap 3 offcanvas in media width > 768px

I am using bootstrap generic offcanvas which is working fine. However, I want to expand collapse the sidebar when the screen width is more than 768px with css3 synchronized animation on both the divs. I want css only method to do this, if css not working, then jquery also fine.

Here is what I tried so far and here is a fullscreen view.

Since I used width: 0; and height: 0; for #sidebar div, it is not animating nicely. Is there any way to do so with the existing offcanvas method? I don't want to change the HTML markup.

HTML

<!-- Navbar Tag Removed to reduce space -->
<!-- /.navbar -->
<div class="container">
    <div class="row row-offcanvas row-offcanvas-left">
        <div class="col-xs-8 col-sm-3 sidebar-offcanvas" id="sidebar" role="navigation">
            <h4>Menu</h4>
            <!-- Content Removed -->
        </div>
        <!--/span-->
        <div class="col-xs-12 col-sm-9 col-main">
            <p>
                <button type="button" class="btn btn-primary btn-xs" data-toggle="offcanvas">Toggle
                    nav</button>
            </p>
            <div class="jumbotron">
                <h1>Hello, world!</h1>
                <p>This is an example to show the potential of an offcanvas layout pattern in Bootstrap.
                    Try some responsive-range viewport sizes to see it in action.</p>
            </div>
            <!-- Content Removed  -->
            <!--/row-->
        </div>
        <!--/span-->

    </div>
    <!--/row-->

</div>
<!--/.container-->

CSS

html,   body {
  overflow-x: hidden; /* Prevent scroll on narrow devices */
}

@media (min-width: 768px) {
    html,   body {
    overflow-x: auto; /* allow scroll */
    }
    .container {
        max-width: 100%;
        width: 100%;
    }
/*Off Canvas */
    .sidebar-offcanvas, .col-main {
        position: relative;
        -webkit-transition: all .25s ease-out;
         -o-transition: all .25s ease-out;
            transition: all .25s ease-out;
  }
    .side-toggle .sidebar-offcanvas {
        left: -100%;
        width: 0;
        height: 0;
  }
    .side-toggle .col-main {
        width:100%;
    }
}

JQUERY

$(document).ready(function () {
    if ($(window).width() < 768) {
        $('[data-toggle="offcanvas"]').click(function () {
            $('.row-offcanvas').toggleClass('active');
        });
    }
    if ($(window).width() > 768){
        $('[data-toggle="offcanvas"]').click(function () {
            $('.row-offcanvas').toggleClass('side-toggle');
        });
    }
});
$(window).resize(function () {
    if ($(window).width() < 768) {
        $('[data-toggle="offcanvas"]').click(function () {
            $('.row-offcanvas').toggleClass('active');
        });
    }
    if ($(window).width() > 768){
        $('[data-toggle="offcanvas"]').click(function () {
            $('.row-offcanvas').toggleClass('side-toggle');
        });
    }
});

Update

  1. When the screen resolution is greater than 768px, the toggle button should be act like the toggling width of both the cols, i.e. #sidebar and .col-main divs. The #sidebar needed to be hidden with linear animation whereas the .col-main' div's width should be expanded to 100% width and vice versa when clicking again.
  2. When the screen resolution is lesser than 768px, the offcanvas should act like the generic Bootstrap Offcanvas template.
  3. While resizing the browser, the script should need to check the screen resolution and do accordingly as mentioned above 1 and 2 points.

Upvotes: 2

Views: 8693

Answers (3)

Ravimallya
Ravimallya

Reputation: 6610

Finally I got to manage the desired output with the help of the answer given by @matty. I also used jquery cookie to retain the viewstate of the sidebar after refreshing the page (post back).

HTML markup is as it is. However, I used the following CSS:

html, body {
    overflow-x: hidden; /* Prevent scroll on narrow devices */
}
@media (min-width: 768px) {
    html, body {
        overflow-x: auto; /* allow scroll */
    }
    .container {
        max-width: 100%;
        width: 100%;
    }
    /** Off Canvas **/
    .sidebar-offcanvas, .col-main {
        position: relative;
    }
    .animate .sidebar-offcanvas, .animate .col-main {
        -webkit-transition: all .25s ease-out;
        -o-transition: all .25s ease-out;
        transition: all .25s ease-out;
    }
    .side-toggle .sidebar-offcanvas {
        width: 0;
        padding: 0;
        overflow: hidden;
    }
    .side-toggle .col-main {
        width: 100%;
    }
}
@media screen and (max-width: 767px) {
    /** Off Canvas **/
    .row-offcanvas {
        position: relative;
        -webkit-transition: all .25s ease-out;
        -o-transition: all .25s ease-out;
        transition: all .25s ease-out;
    }
    .row-offcanvas-right {
        right: 0;
    }
    .row-offcanvas-left {
        left: 0;
    }
    .row-offcanvas-right .sidebar-offcanvas {
        right: -66.66666667%; /* 8 columns */
    }
    .row-offcanvas-left .sidebar-offcanvas {
        left: -66.66666667%; /* 8 columns */
    }
    .row-offcanvas-right.active {
        right: 66.66666667%; /* 8 columns */
    }
    .row-offcanvas-left.active {
        left: 66.66666667%; /* 8 columns */
    }
    .sidebar-offcanvas {
        position: absolute;
        top: 0;
        width: 66.66666667%; /* 8 columns */
    }
    .row-offcanvas-left .sidebar-offcanvas {
        margin-left: 15px;
    }
}

Also, I used jquery Cookie plugin to store the collapsed or expanded state of the sidebar in browser cookies. The script I used is:

$(document).ready(function () {
    var toggle = $.cookie('toggle');
    if ($(window).width() > 768 && toggle === "hide") {
        $('.row-offcanvas').addClass('side-toggle');
    }
    $('[data-toggle="offcanvas"]').click(function () {
        $('.row-offcanvas').toggleClass('active').toggleClass('side-toggle');
        if ($('#sidebar').parent().hasClass('active')) {
            $.cookie('toggle', 'hide');
        }
        if (toggle === "hide") {
            $.removeCookie('toggle');
        }
    });
    $(window).resize(function () {
        if ($(window).width() < 768) {
            $('.row-offcanvas').removeClass('animate');
        } else {
            $('.row-offcanvas').addClass('animate');
        }
        if ($(window).width() > 768 && toggle === "hide") {
            $('.row-offcanvas').addClass('side-toggle');
        }
    });
    $(window).trigger('resize');
});

JsBin Edit is here and Full screen preview is here. Please let me know, if you've any doubts/clarifications.

Thanks again matty to bring me in the right direction.

Upvotes: 1

mkutyba
mkutyba

Reputation: 1427

Is it what you want? http://jsbin.com/yageheruludo/4/edit

I changed JS:

   $('[data-toggle="offcanvas"]').click(function () {
      $('.row-offcanvas').toggleClass('active').toggleClass('side-toggle');
   });
   $(window).resize(function () {
      if ($(window).width() < 768) {
          $('.row-offcanvas').removeClass('animate');
      } else {
          $('.row-offcanvas').addClass('animate');
      }
   });

and CSS:

  .sidebar-offcanvas, .col-main {
    position: relative;
  }
  .animate .sidebar-offcanvas, .animate .col-main {
    -webkit-transition: all .25s ease-out;
         -o-transition: all .25s ease-out;
            transition: all .25s ease-out;
  }
  .side-toggle .sidebar-offcanvas {
    width: 0;
    padding: 0;
    overflow: hidden;
  }

edit

Before first window resize the animation doesn't work.

http://jsbin.com/yageheruludo/6/edit

Change js to this:

   $('[data-toggle="offcanvas"]').click(function () {
      $('.row-offcanvas').toggleClass('active').toggleClass('side-toggle');
   });
   $(window).resize(function () {
      if ($(window).width() < 768) {
          $('.row-offcanvas').removeClass('animate');
      } else {
          $('.row-offcanvas').addClass('animate');
      }
   });
   $(window).trigger('resize'); // added this line

What do you mean "not animating (...) after change the duration"? You mean "orientation"?

Upvotes: 6

CodingWithSpike
CodingWithSpike

Reputation: 43728

Part of the problem is your resize handler. Every time the window is resized, you add another click handler, so if you resize the window twice, there will be 2 click handlers that will toggle the class twice, putting it right back where it was.

Should be closer to:

$(window).resize(function () {
    if ($(window).width() < 768) {
        $('.row-offcanvas').toggleClass('active');
    }
    if ($(window).width() > 768){
        $('.row-offcanvas').toggleClass('side-toggle');
    }
});

But even that isn't quite right, because it will toggle the class on each resize event, so as the user tries to resize the window, the div will keep changing as they drag the window to resize it.

Maybe what you actually want is:

$(window).resize(function () {
    if ($(window).width() < 768) {
        $('.row-offcanvas').addClass('active');
        $('.row-offcanvas').removeClass('side-toggle');
    } else {
        $('.row-offcanvas').removeClass('active');
        $('.row-offcanvas').addClass('side-toggle');
    }
});

I don't know if that is the entire problem, but it is definitely part of it.

Upvotes: 1

Related Questions