Search code examples
cssbootstrap-5grid-layout

How can I move a sidebar column between central content columns for mobile?


I want to have a situation where I have the following elements:

  • Left Sidebar
  • Main Content
  • Right Sidebar
  • Extra Content

What I am trying to accomplish is:

  • When expanded on larger screens: Have the "Extra Content" line up immediately below the main content and share the same width, with no gap between the main content and extra content.
  • When collapsed on small screens: Have all elements stack vertically with full width, but the Right Sidebar should be between Main Content and Extra Content.

My attempt so far:

.row {
  background: #dfdfdf;
}

.col {
  background: #f8f9fa;
  border: solid 1px #6c757d;
  padding: 10px;
}

.tall {
  height: 100px;
}

.xtall {
  height: 200px;
}

.container.my-size .row {
  margin-top: 30px;
}

.container.my-size .row .col {
  background: #cdceff;
}

#sidebar-right {
  float: right;
}

#main {
  background: #ffeecd;
}

#extra {
  background: #ffeecd;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<div class="container my-grids">
  <div class="row flex-column flex-sm-row">
    <div id="sidebar-left" class="col col-sm-3 order-sm-1 align-self-baseline">
      <div class="tall">Left Sidebar</div>
    </div>
    <div id="main" class="col col-sm-6 order-sm-2 align-self-baseline">
      <div class="">Main Content</div>
    </div>
    <div id="sidebar-right" class="col col-sm-3 order-sm-3 align-self-baseline">
      <div class="tall">Right Sidebar</div>
    </div>
    <div id="extra" class="col col-sm-6 order-sm-4 align-self-baseline">
      <div class="">Extra Content</div>
    </div>

  </div>
</div>

<!-- Have a row which displays the current screen size -->
<div class="container my-size">
  <div class="row">
    <div class="col col-md-12 d-xs-block d-sm-none">Screen is <b>xs</b></div>
    <div class="col col-md-12 d-none d-sm-block d-md-none">Screen is <b>sm</b></div>
    <div class="col col-md-12 d-none d-md-block d-lg-none">Screen is <b>md</b></div>
    <div class="col col-md-12 d-none d-lg-block d-xl-none">Screen is <b>lg</b></div>
    <div class="col col-md-12 d-none d-xl-block d-xxl-none">Screen is <b>xl</b></div>
    <div class="col col-md-12 d-none d-xxl-block">Screen is <b>xxl</b></div>
  </div>
</div>

Example Fiddle of what I have so-far

What is currently happening:

Image of what is currently happening when the sidebars are taller than the main content

Image of what is currently happening when than main content is taller than the sidebars

Image of what is currently happening on small screens (what I want)

What I want to happen:

Image of what I want on larger screens

Image of what I want on larger screens

Image of what I want on small screens

I am currently using Bootstrap 3 and would be ideal to have a solution in Bootstrap 3, but am willing to have a Bootstrap 4/5 solution if that's the only way.


Solution

  • Figured out how to accomplish this.

    Changes made:

    • Moved Main Content, Extra Content, and Right Sidebar into a new "inner container"
    • Set this inner container to take up the remainder of the columns besides First Column on larger screens, and full width on smaller screens.
    • Set the elements within the inner container to use floats and column styling for their width but disable the flex box.

    Fiddle with solution

    .row { 
      background: #dfdfdf;
    }
    
    .col {
      background: #f8f9fa;
      border: solid 1px #6c757d;
      padding: 10px;
    }
    
    .tall {
      height: 100px;
    }
    
    .xtall {
      height: 200px;
    }
    
    .container.my-size .row {
      margin-top: 30px;
    }
    
    .container.my-size .row .col {
      background: #cdceff;
    }
    
    #sidebar-right {
      float: right;
    }
    
    #main {
      background: #ffeecd;
      float: left;
    }
    
    #extra {
      background: #ffeecd;
      float: left;
    }
    
    #inner-container {
      padding: 0;
    }
    
    #inner-container .col {
      flex: none;
    }
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet" />
    
    <div class="container my-grids">
      <div class="row flex-column flex-sm-row">
        <div id="sidebar-left" class="col col-sm-3 align-self-baseline">
          <div class="tall">Left Sidebar</div>
        </div>
        <div id="inner-container" class="col col-sm-9">
          <div id="main" class="col col-sm-8">
            <div class="xtall">Main Content</div>
          </div>
          <div id="sidebar-right" class="col col-sm-4">
            <div class="tall">Right Sidebar</div>
          </div>
          <div id="extra" class="col col-sm-8">
            <div class="">Extra Content</div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Have a row which displays the current screen size -->
    <div class="container my-size">
      <div class="row">
        <div class="col col-md-12 d-xs-block d-sm-none">Screen is <b>xs</b></div>
        <div class="col col-md-12 d-none d-sm-block d-md-none">Screen is <b>sm</b></div>
        <div class="col col-md-12 d-none d-md-block d-lg-none">Screen is <b>md</b></div>
        <div class="col col-md-12 d-none d-lg-block d-xl-none">Screen is <b>lg</b></div>
        <div class="col col-md-12 d-none d-xl-block d-xxl-none">Screen is <b>xl</b></div>
        <div class="col col-md-12 d-none d-xxl-block">Screen is <b>xxl</b></div>
      </div>
    </div>