14

I have a 3-col-layout like

<div class="container">
    <div class="row">
        <div class="col-md-2" id="block1">#block1 .col-md-2</div>
        <div class="col-md-2" id="block2">#block2 .col-md-2</div>
        <div class="col-md-8" id="block3">#block3 .col-md-8</div>
    </div>
</div>

----------------------------------------------------------------
|          |          |                                        |
|          |          |                                        |
|          |          |                                        |
|          |          |                                        |
|  #block1 |  #block2 |                 #block3                |
|  .col-2  |  .col-2  |                 .col-8                 |
|          |          |                                        |
|          |          |                                        |
|          |          |                                        |
|          |          |                                        |
----------------------------------------------------------------

On small screens the columns slide one below the other:

-------------------------
|                       |
|                       |
|                       |
|                       |
|        #block1        |
|        .col-12        |
|                       |
|                       |
|                       |
|                       |
-------------------------
-------------------------
|                       |
|                       |
|                       |
|                       |
|        #block2        |
|        .col-12        |
|                       |
|                       |
|                       |
|                       |
-------------------------
-------------------------
|                       |
|                       |
|                       |
|                       |
|        #block3        |
|        .col-12        |
|                       |
|                       |
|                       |
|                       |
-------------------------

Now I want the first two columns to collapse like the typical Bootstrap navigation:

-------------------------
|   #block1 .col-12   ≡ |
-------------------------
-------------------------
|   #block2 .col-12   ≡ |
-------------------------
-------------------------
|                       |
|                       |
|                       |
|                       |
|                       |
|   #block3 .col-12     |
|                       |
|                       |
|                       |
|                       |
-------------------------

I tried to "clone" it from the Bootstrap starter template, but could not found out, what exactly manages this behavior.

How to get DIVs collapsing automatically on small screens and provide a toggle button? Is it possible to do this by using only Bootstrap classes (without additional JS)?

TylerH
  • 20,799
  • 66
  • 75
  • 101
automatix
  • 14,018
  • 26
  • 105
  • 230

6 Answers6

5

Here you go with a solution https://jsfiddle.net/mhmvhsf6/

.col{
  border: 1px dotted #000;
  min-height: 50px;
}

.collapse {
  height: 200px;
  background: rgba(0,0,0,0.3);
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container-fluid">
  <div class="row">
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col">
      <div class="navbar-header navbar-inverse">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span> 
        </button>
      </div>
      <div class="collapse navbar-collapse" id="myNavbar">
        
      </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col">
      <div class="navbar-header navbar-inverse">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#collapse2">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span> 
        </button>
      </div>
      <div class="collapse navbar-collapse" id="collapse2">
        
      </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col"></div>
  </div>
</div>

Hope this will help you.

For Col-1 & col-2, content will go inside the collapse class container.

Shiladitya
  • 12,003
  • 15
  • 25
  • 38
  • Thank you! In principle the solution is working. The only problem, I have with it, is, that the collapsing is activated NOT at the same moment / NOT for the same window width as when third column moves down. That means: When I'm making the window smaller (ans smaller, and smaller...) at some moment the third column slides under the other two. Exactly at this moment I would like the other two columns to collapse and all the three blocks build one single column. But the appear only much later. So I have a constellation, when the third col is under the first two, that are not collapsed. – automatix Aug 16 '17 at 21:39
  • If your requirement is like that then use **media query** for col-sm in navbar. – Shiladitya Aug 17 '17 at 05:16
  • For customization of your navbar collapse, have a look into https://stackoverflow.com/questions/22329606/bootstrap-navbar-collapse-media-query-on-custom-width – Shiladitya Aug 19 '17 at 03:28
  • @automatix. Here is the updated solution https://jsfiddle.net/mhmvhsf6/1/ – Shiladitya Aug 23 '17 at 06:26
3

I attempted to make what you are asking for using purely CSS. I did not use bootstrap, but emulated the idea of the grid and what not with very simple CSS. I also used a checkbox to control the toggle of the navbar, but you can move the toggle off screen and use a hamburger if that is what you need!

By using max-height and a special wrapper for any content I wish to have toggled this has become possible. Any CSS transitions can be replaced with Javascript.

HTML

<div class="container">
    <div class="row">
        <div class="col col-1">

            <input class="toggle toggle-inputs" id="toggle1" type="checkbox" />
            <label class="toggle-inputs" for="toggle1">Toggle</label>

            <div class="mobile-toggle">
                <p>Paragraph 1</p>
            </div>
        </div>

        <div class="col col-2">

            <input class="toggle toggle-inputs" id="toggle2" type="checkbox" />
            <label class="toggle-inputs" for="toggle2">Toggle</label>

            <div class="mobile-toggle">
                <p>Paragraph 2</p>
            </div>
        </div>

        <div class="col col-3">
            <p>Paragraph 3</p>
        </div>


    </div>
</div>

The relevant CSS

.toggle-inputs {
    display: none;
}

.toggle:checked ~ .mobile-toggle {
    max-height: 2000px; /* make larger than it might ever be */
}

@media (max-width: 768px) {

    .toggle-inputs {
        display: inline;
    }

    .mobile-toggle {
        max-height: 0px;
        overflow: hidden;

        -webkit-transition: max-height 0.3s ease-out;
             -o-transition: max-height 0.3s ease-out;
            -ms-transition: max-height 0.3s ease-out;
                transition: max-height 0.3s ease-out;
    }

}

Here is a JSFiddle with all of the working parts.

Jacob Raccuia
  • 1,666
  • 1
  • 16
  • 25
3

you should run media query on nav with reference of custom wrapper class, do copy paste, check this code, it works

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">

    <title>Starter Template for Bootstrap</title>

  </head>
  <body>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
      .col{
  border: 1px dotted #000;
  min-height: 50px;
}

.collapse {
  height: 200px;
  background: rgba(0,0,0,0.3);
}
@media (max-width: 992px) {
    .custom_wrapper .navbar-header {
        float: none;
    }
    .custom_wrapper .navbar-left, .custom_wrapper .navbar-right {
        float: none !important;
    }
    .custom_wrapper .navbar-toggle {
        display: block;
    }
    .custom_wrapper .navbar-collapse {
        border-top: 1px solid transparent;
        box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
    }
    .custom_wrapper .navbar-fixed-top {
        top: 0;
        border-width: 0 0 1px;
    }
    .custom_wrapper .navbar-collapse.collapse {
        display: none!important;
    }
    .custom_wrapper .navbar-nav {
        float: none!important;
        margin-top: 7.5px;
    }
    .custom_wrapper .navbar-nav>li {
        float: none;
    }
    .custom_wrapper .navbar-nav>li>a {
        padding-top: 10px;
        padding-bottom: 10px;
    }
    .custom_wrapper .collapse.in{
        display:block !important;
    }
}
  </style>
<div class="container-fluid custom_wrapper">
  <div class="row">
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col">

      <div class="navbar-header navbar-inverse">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span> 
        </button>
      </div>
      <div class="collapse navbar-collapse" id="myNavbar">
        test
      </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col">

      <div class="navbar-header navbar-inverse">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#collapse2">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span> 
        </button>
      </div>
      <div class="collapse navbar-collapse" id="collapse2">
        test2
      </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-4 col-lg-4 col">
        test 3
    </div>
  </div>
</div>
  </body>
</html>
  • @automatix, have you checked this? – Muhammad Akber Khan Aug 19 '17 at 11:47
  • Thank you very much! Yes, that works! There is just a mini bug. When I resize the window slowly, there is one point, when the slim columns (the first two `col-2` columns) get the "minimized" look to early. See the screenshot [here](https://ibb.co/iLmK45). It's a little bug and not very important, but if you know, how to avoid that, it would be nice. – automatix Aug 20 '17 at 17:10
  • If works can you upvote? I will update my answer if i got an idea – Muhammad Akber Khan Aug 21 '17 at 01:55
2

Based on my understanding of my question, I believe that your requirements are as such:

  1. Use accordion to allow hiding of column contents when screen sizes are mobile (in bootstrap terms, that will be a width less than the md designation).
  2. Use normal grid layout when width is wider than mobile (width greater than the md designation).

Note that the md designation refers to a width of 992px :) that will come into handy in our solution.

There are several ways to tackle your issue: we can use a pure JS-based solution where we dynamically create and destroy an accordion based on viewport width, listened on by the $(window).resize() event, but that is highly inefficient and extremely unperformant (unless you throttle the event, which brings around another host of issues such as responsiveness).

The solution I have explored will be simply to use a standard bootstrap accordion/collapsible markup, with some simple CSS tricky to get it to work:

  • We assume a default layout of accordions, but built in some grid classes for use in wider viewports
  • We use @media (min-width: <md-width>), a.k.a. @media (min-width: 992px) to override certain styles in the accordion panels so that they do not interfere with grid layout at wider viewports.

With that in mind, we can look into structuring your markup as such:

  • .container
    • .row
    • .panel-group, which houses all your accordion things
      • .panel, which houses your panel content. This can be repeated for as many columns/panels you want
      • .panel-heading + .visible-xs .visible-sm so that the nested panel controls are visible only at narrow viewports (sizes < md)
      • .panel-collapse + .col-md-4, the content of your individual panel/columns with the appropriate width for grid layout

With this structure in mind, here is a template that can be reused for all panels:

<!-- First panel/column -->
<div class="panel">

  <!-- Panel heading, visible at screen sizes < md (i.e. xs and sm only) -->
  <div class="panel-heading visible-xs visible-sm">
    <h1 class="panel-title">
      <a href="#col1" data-parent="#accordion" data-toggle="collapse" aria-expanded="true" aria-controls="col1">Column 1</a>
    </h1>
  </div>

  <!-- Panel content -->
  <div id="col1" class="col-md-4 panel-collapse collapse in" role="tabpanel" aria-labelledby="col1">
    <!-- Insert content here -->
  </div>

</div>

Note: I do not see a utility for a nav-toggle here, because it is typically used to stash additional navigation links away when the viewport is too narrow. However, if you insist on using it, you can modify your markup within .panel-heading as such:

<h1 class="panel-title navbar navbar-default">
  <div class="navbar-header">
    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#col1" aria-expanded="true" aria-controls="col1">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
    <a class="navbar-brand" href="#col1" data-parent="#accordion" data-toggle="collapse" aria-expanded="true" aria-controls="col1">Column 1</a>
  </div>
</h1>

Remember the default panel styles? They add a margin and border to the .panel elements which interferes with grid layout, and the .panel-collapse are hidden when the .collapse class is present. For that, we simply want a media query that disables these styles at width greater than or equals to the md designation, i.e. @media (min-width: 992px), so that

  • .panel-collapse.collapse will be forced to display (i.e. panels should be displayed regardless if they have been collapsed or not in narrow viewports)
  • .panel should not have margins and borders that interfere with grid layout

Therefore, we do this:

@media (min-width: 992px) {
  #accordion .panel-collapse.collapse {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
  }
  #accordion .panel {
    margin: 0;
    border: none;
  }
}

With all these in mind, here is a proof-of-concept example (you can also refer to an example on jsfiddle). Note that you will have to run the code snippet and then open/expand it in full view, so that you can play around with different viewport sizes :)

@media (min-width: 992px) {
  #accordion .panel-collapse.collapse {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
  }
  #accordion .panel {
    margin: 0;
    border: none;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<div class="container">
  <div class="row">
    <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="false">

      <!-- First panel/column -->
      <div class="panel">
        <div class="panel-heading visible-xs visible-sm">
          <h1 class="panel-title">
            <a href="#col1" data-parent="#accordion" data-toggle="collapse" aria-expanded="true" aria-controls="col1">Column 1</a>
          </h1>
        </div>
        <div id="col1" class="col-md-4 panel-collapse collapse in" role="tabpanel" aria-labelledby="col1">
          <h2>Column/Panel header 1</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta dignissimos unde nemo sed necessitatibus vitae ipsum, maxime quaerat dolorum dolorem</p>
        </div>
      </div>

      <!-- Second panel/column -->
      <div class="panel">
        <div class="panel-heading visible-xs visible-sm">
          <h1 class="panel-title">
            <a href="#col2" data-parent="#accordion" data-toggle="collapse" aria-expanded="false" aria-controls="col2">Column 2</a>
          </h1>
        </div>
        <div id="col2" class="col-md-4 panel-collapse collapse" role="tabpanel" aria-labelledby="col2">
          <h2>Column/Panel header 2</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta dignissimos unde nemo sed necessitatibus vitae ipsum, maxime quaerat dolorum dolorem</p>
        </div>
      </div>

      <!-- Third panel/column -->
      <div class="panel">
        <div class="panel-heading visible-xs visible-sm">
          <h1 class="panel-title">
            <a href="#col3" data-parent="#accordion" data-toggle="collapse" aria-expanded="false" aria-controls="col3">Column 3</a>
          </h1>
        </div>
        <div id="col3" class="col-md-4 panel-collapse collapse" role="tabpanel" aria-labelledby="col3">
          <h2>Column/Panel header 3</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta dignissimos unde nemo sed necessitatibus vitae ipsum, maxime quaerat dolorum dolorem</p>
        </div>
      </div>

    </div>
  </div>
Terry
  • 63,248
  • 15
  • 96
  • 118
0

Responsible for the collapse in Bootstrap 3.x is collapse.js, but technically speaking wouldn't be so difficult to achieve with CSS (not just Bootstrap classes) and at least some JS to handle the click on the toggle button. If you would be interested in this, let me know, so I can provide some code.

Kostas Siabanis
  • 2,989
  • 2
  • 20
  • 22
0

It is possible to collapse the menu manually just like bootstrap without actually using it. This can be done by combining

window.onresize = resize;
function resize()
{
 //code to be run after window resize
}

with window.innerWidthproperty to find the current width of the window.

For your example, you could use the following code to implement the functionalities:

window.onresize = resize;
function eventresize()
{
 var w = window.innerWidth;
if(w<370)
{
 var a =document.querySelectorAll(".col-md-4")[0];
 var b = document.querySelectorAll(".col-md-4")[1];
 a.innerHTML="//collapsed nav-bar HTML code";
 b.innerHTML="//collapsed nav-bar HTML code";
 }
}

The width of the small screen is assumed to be below 370px. The resize of the browser window triggers a function which checks the width of the web browser and changes the innerHTML codes of the first two columns if the condition for small screen is satisfied. Alternatively we can also add an event listener registered to the window, which triggers the event function each time the window is resized.

window.addEventListener('resize', eventresize);

Also it is not possible to create the toggle button without additional js file.

Aniruddha Alek
  • 227
  • 3
  • 10